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

tokenp.h File Reference

#include "ntos.h"
#include "sep.h"
#include "seopaque.h"

Go to the source code of this file.

Classes

struct  _TOKEN
struct  _IOBJECT_TYPE_LIST

Defines

#define IF_TOKEN_GLOBAL(FlagName)   if (FALSE)
#define TokenDiagPrint(FlagName, _Text_)   ;
#define TOKEN_DIAG_TOKEN_LOCKS   ((ULONG) 0x00000001L)
#define TOKEN_DEFAULT_DYNAMIC_CHARGE   500
#define OBJECT_SUCCESS_AUDIT   0x1
#define OBJECT_FAILURE_AUDIT   0x2
#define SepAcquireTokenReadLock(T)
#define SepAcquireTokenWriteLock(T)
#define SepReleaseTokenReadLock(T)
#define SepReleaseTokenWriteLock(T, M)
#define SepArrayPrivilegeAttributes(P, I)   ( (P)[I].Attributes )
#define SepTokenPrivilegeAttributes(T, I)   ( (T)->Privileges[I].Attributes )
#define SepArrayGroupAttributes(G, I)   ( (G)[I].Attributes )
#define SepTokenGroupAttributes(T, I)   ( (T)->UserAndGroups[I].Attributes )

Typedefs

typedef _TOKEN TOKEN
typedef _TOKENPTOKEN
typedef _IOBJECT_TYPE_LIST IOBJECT_TYPE_LIST
typedef _IOBJECT_TYPE_LISTPIOBJECT_TYPE_LIST

Functions

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)
NTSTATUS SepAdjustGroups (IN PTOKEN Token, IN BOOLEAN MakeChanges, IN BOOLEAN ResetToDefault, IN ULONG GroupCount OPTIONAL, IN PSID_AND_ATTRIBUTES NewState OPTIONAL, OUT PTOKEN_GROUPS PreviousState OPTIONAL, OUT PSID SidBuffer OPTIONAL, OUT PULONG ReturnLength, OUT PULONG ChangeCount, OUT PBOOLEAN ChangesMade)
NTSTATUS SepAdjustPrivileges (IN PTOKEN Token, IN BOOLEAN MakeChanges, IN BOOLEAN DisableAllPrivileges, IN ULONG PrivilegeCount OPTIONAL, IN PLUID_AND_ATTRIBUTES NewState OPTIONAL, OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PULONG ReturnLength, OUT PULONG ChangeCount, OUT PBOOLEAN ChangesMade)
VOID SepAppendDefaultDacl (IN PTOKEN Token, IN PACL PAcl)
VOID SepAppendPrimaryGroup (IN PTOKEN Token, IN PSID PSid)
NTSTATUS SepDuplicateToken (IN PTOKEN ExistingToken, IN POBJECT_ATTRIBUTES ObjectAttributes, IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel OPTIONAL, IN KPROCESSOR_MODE RequestorMode, OUT PTOKEN *DuplicateToken)
NTSTATUS SepFilterToken (IN PTOKEN ExistingToken, IN KPROCESSOR_MODE RequestorMode, IN ULONG Flags, IN ULONG GroupCount, IN PSID_AND_ATTRIBUTES GroupsToDisable OPTIONAL, IN ULONG PrivilegeCount, IN PLUID_AND_ATTRIBUTES PrivilegesToDelete OPTIONAL, IN ULONG SidCount, IN PSID_AND_ATTRIBUTES RestrictedSids OPTIONAL, IN ULONG SidLength, OUT PTOKEN *FilteredToken)
BOOLEAN SepSidInSidAndAttributes (IN PSID_AND_ATTRIBUTES SidAndAttributes, IN ULONG SidCount, IN PSID PrincipalSelfSid, IN PSID Sid)
VOID SepRemoveDisabledGroupsAndPrivileges (IN PTOKEN Token, IN ULONG Flags, IN ULONG GroupCount, IN PSID_AND_ATTRIBUTES GroupsToDisable, IN ULONG PrivilegeCount, IN PLUID_AND_ATTRIBUTES PrivilegesToDelete)
VOID SepFreeDefaultDacl (IN PTOKEN Token)
VOID SepFreePrimaryGroup (IN PTOKEN Token)
BOOLEAN SepIdAssignableAsOwner (IN PTOKEN Token, IN ULONG Index)
VOID SepMakeTokenEffectiveOnly (IN PTOKEN Token)
BOOLEAN SepTokenInitialization (VOID)
VOID SepTokenDeleteMethod (IN PVOID Token)
BOOLEAN SepPrivilegeCheck (IN PTOKEN Token, IN OUT PLUID_AND_ATTRIBUTES RequiredPrivileges, IN ULONG RequiredPrivilegeCount, IN ULONG PrivilegeSetControl, IN KPROCESSOR_MODE PreviousMode)
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)
BOOLEAN SepObjectInTypeList (IN GUID *ObjectType, IN PIOBJECT_TYPE_LIST ObjectTypeList, IN ULONG ObjectTypeListLength, OUT PULONG ReturnedIndex)

Variables

GENERIC_MAPPING SepTokenMapping
POBJECT_TYPE SepTokenObjectType
ERESOURCE SepTokenLock


Define Documentation

#define IF_TOKEN_GLOBAL FlagName   )     if (FALSE)
 

Definition at line 87 of file tokenp.h.

#define OBJECT_FAILURE_AUDIT   0x2
 

Definition at line 377 of file tokenp.h.

Referenced by SepAdtOpenObjectAuditAlarm(), SepAuditTypeList(), and SepSetAuditInfoForObjectType().

#define OBJECT_SUCCESS_AUDIT   0x1
 

Definition at line 376 of file tokenp.h.

Referenced by SepAdtOpenObjectAuditAlarm(), SepAuditTypeList(), and SepSetAuditInfoForObjectType().

#define SepAcquireTokenReadLock  ) 
 

Value:

Definition at line 413 of file tokenp.h.

Referenced by NtDuplicateToken(), NtFilterToken(), NtQueryInformationToken(), SeAccessCheckByType(), SeFilterToken(), SeGetTokenControlInformation(), SeIsChildToken(), SeIsChildTokenByPointer(), SeLockSubjectContext(), SepDuplicateToken(), SepFilterToken(), SepIdAssignableAsGroup(), SepPrivilegeCheck(), SepTokenIsOwner(), SepValidOwnerSubjectContext(), SeQueryAuthenticationIdToken(), SeQueryInformationToken(), and SeQuerySessionIdToken().

#define SepAcquireTokenWriteLock  ) 
 

Value:

Definition at line 416 of file tokenp.h.

Referenced by NtAdjustGroupsToken(), NtAdjustPrivilegesToken(), NtSetInformationToken(), and SeSetSessionIdToken().

#define SepArrayGroupAttributes G,
 )     ( (G)[I].Attributes )
 

Definition at line 479 of file tokenp.h.

Referenced by SepAdjustGroups(), and SepCreateToken().

#define SepArrayPrivilegeAttributes P,
 )     ( (P)[I].Attributes )
 

Definition at line 460 of file tokenp.h.

Referenced by SepAdjustPrivileges().

#define SepReleaseTokenReadLock  ) 
 

Value:

Definition at line 419 of file tokenp.h.

Referenced by NtDuplicateToken(), NtFilterToken(), NtQueryInformationToken(), SeAccessCheckByType(), SeFilterToken(), SeGetTokenControlInformation(), SeIsChildToken(), SeIsChildTokenByPointer(), SepDuplicateToken(), SepFilterToken(), SepIdAssignableAsGroup(), SepPrivilegeCheck(), SepTokenIsOwner(), SepValidOwnerSubjectContext(), SeQueryAuthenticationIdToken(), SeQueryInformationToken(), SeQuerySessionIdToken(), and SeUnlockSubjectContext().

#define SepReleaseTokenWriteLock T,
 ) 
 

Value:

{ \ if ((M)) { \ ExAllocateLocallyUniqueId( &((PTOKEN)(T))->ModifiedId ); \ } \ SepReleaseTokenReadLock( T ); \ }

Definition at line 444 of file tokenp.h.

Referenced by NtAdjustGroupsToken(), NtAdjustPrivilegesToken(), NtSetInformationToken(), and SeSetSessionIdToken().

#define SepTokenGroupAttributes T,
 )     ( (T)->UserAndGroups[I].Attributes )
 

Definition at line 489 of file tokenp.h.

Referenced by SepAdjustGroups(), SepIdAssignableAsOwner(), and SepMakeTokenEffectiveOnly().

#define SepTokenPrivilegeAttributes T,
 )     ( (T)->Privileges[I].Attributes )
 

Definition at line 470 of file tokenp.h.

Referenced by SepAdjustPrivileges(), and SepMakeTokenEffectiveOnly().

#define TOKEN_DEFAULT_DYNAMIC_CHARGE   500
 

Definition at line 124 of file tokenp.h.

Referenced by SepCreateToken().

#define TOKEN_DIAG_TOKEN_LOCKS   ((ULONG) 0x00000001L)
 

Definition at line 108 of file tokenp.h.

#define TokenDiagPrint FlagName,
_Text_   )     ;
 

Definition at line 93 of file tokenp.h.


Typedef Documentation

typedef struct _IOBJECT_TYPE_LIST IOBJECT_TYPE_LIST
 

Referenced by SeCaptureObjectTypeList().

typedef struct _IOBJECT_TYPE_LIST * PIOBJECT_TYPE_LIST
 

typedef struct _TOKEN * PTOKEN
 

typedef struct _TOKEN TOKEN
 

Referenced by CmpParseInfBuffer().


Function Documentation

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 }

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 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 }

NTSTATUS SepAdjustGroups IN PTOKEN  Token,
IN BOOLEAN  MakeChanges,
IN BOOLEAN  ResetToDefault,
IN ULONG GroupCount  OPTIONAL,
IN PSID_AND_ATTRIBUTES NewState  OPTIONAL,
OUT PTOKEN_GROUPS PreviousState  OPTIONAL,
OUT PSID SidBuffer  OPTIONAL,
OUT PULONG  ReturnLength,
OUT PULONG  ChangeCount,
OUT PBOOLEAN  ChangesMade
 

Definition at line 1099 of file tokenadj.c.

References ANYSIZE_ARRAY, ASSERT, FALSE, NTSTATUS(), PAGED_CODE, RtlCopySid(), RtlEqualSid(), SeLengthSid, SepArrayGroupAttributes, SepTokenGroupAttributes, Token, and TRUE.

Referenced by NtAdjustGroupsToken().

01115 : 01116 01117 This routine is used to walk the groups array in a token as a 01118 result of a request to adjust groups. 01119 01120 If the MakeChanges parameter is FALSE, this routine simply determines 01121 what changes are needed and how much space is necessary to save the 01122 current state of changed groups. 01123 01124 If the MakeChanges parameter is TRUE, this routine will not only 01125 calculate the space necessary to save the current state, but will 01126 actually make the changes. 01127 01128 This routine makes the following assumptions: 01129 01130 1) The token is locked for exclusive access. 01131 01132 2) The NewState parameter is captured and accesses 01133 to it will not result in access violations. 01134 01135 4) Any access violations encountered may leave the request 01136 partially completed. It is the calling routine's responsibility 01137 to catch exceptions. 01138 01139 5) The calling routine is responsible for inrementing the token's 01140 ModifiedId field. 01141 01142 Arguments: 01143 01144 Token - Pointer to the token to act upon. 01145 01146 MakeChanges - A boolean value indicating whether the changes should 01147 actually be made, or just evaluated. A value of TRUE indicates 01148 the changes should be made. 01149 01150 ResetToDefault - Indicates that the groups are to be reset to their 01151 default enabled/disabled state. 01152 01153 GroupCount - This parameter is required only if the NewState parameter 01154 is used. In that case, this parameter indicates how many entries are 01155 in the NewState parameter. 01156 01157 NewState - This parameter points to a SID_AND_ATTRIBUTES array 01158 containing the groups whose states are to be adjusted 01159 (disabled or enabled). Only the Enabled flag of the 01160 attributes associated with each group is used. It provides 01161 the new value that is to be assigned to the group in the 01162 token. If the ResetToDefault argument is specified as TRUE, 01163 then this argument is ignored. Otherwise, it must be passed. 01164 01165 PreviousState - This (optional) parameter points to a buffer to 01166 receive the state of any groups actually changed by this 01167 request. This information is formated as a TOKEN_GROUPS data 01168 structure which may be passed as the NewState parameter in a 01169 subsequent call to NtAdjustGroups to restore the original state 01170 of those groups. It is the caller's responsibility to make 01171 sure this buffer is large enough to receive all the state 01172 information. 01173 01174 SidBuffer - Pointer to buffer to receive the SID values corresponding 01175 to the groups returned in the PreviousState argument. 01176 01177 ReturnLength - Points to a buffer to receive the number of bytes needed 01178 to retrieve the previous state information of changed privileges. 01179 This parameter is ignored if the PreviousState argument is not 01180 passed. 01181 01182 ChangeCount - Points to a ULONG to receive the number of groups 01183 which were adjusted (or would be adjusted, if changes are made). 01184 01185 ChangesMade - Points to a boolean flag which is to receive an indication 01186 as to whether any changes were made as a result of this call. This 01187 is expected to be used to decide whether or not to increment the 01188 token's ModifiedId field. 01189 01190 Return Value: 01191 01192 STATUS_SUCCESS - Call completed sccessfully. 01193 01194 STATUS_NOT_ALL_ASSIGNED - Indicates not all the specified adjustments 01195 have been made (or could be made, if update wasn't requested). 01196 01197 STATUS_CANT_DISABLE_MANDATORY - Not all adjustments were made (or could 01198 be made, if update not requested) because an attempt was made to 01199 disable a mandatory group. The state of the groups is left 01200 in an underterministic state if update was requested. 01201 01202 01203 --*/ 01204 { 01205 01206 NTSTATUS CompletionStatus = STATUS_SUCCESS; 01207 01208 ULONG OldIndex; 01209 ULONG NewIndex; 01210 ULONG SidLength; 01211 ULONG LocalReturnLength = 0; 01212 PSID NextSid; 01213 BOOLEAN Found; 01214 ULONG MatchCount = 0; 01215 BOOLEAN EnableGroup; 01216 BOOLEAN DisableGroup; 01217 ULONG TokenGroupAttributes; 01218 01219 SID_AND_ATTRIBUTES CurrentGroup; 01220 01221 PAGED_CODE(); 01222 01223 // 01224 // NextSid is used to copy group SID values if asked for previous state. 01225 // 01226 01227 NextSid = SidBuffer; 01228 01229 01230 // 01231 // Walk through the groups array to determine which need to be 01232 // adjusted. 01233 // 01234 01235 OldIndex = 1; // Don't evaluate the 0th entry (user ID) 01236 (*ChangeCount) = 0; 01237 01238 while (OldIndex < Token->UserAndGroupCount) { 01239 01240 CurrentGroup = Token->UserAndGroups[OldIndex]; 01241 01242 if (ResetToDefault) { 01243 01244 TokenGroupAttributes = SepTokenGroupAttributes(Token,OldIndex); 01245 01246 // 01247 // If the group is enabled by default and currently disabled, 01248 // then we must enable it. 01249 // 01250 01251 EnableGroup = (BOOLEAN)( (TokenGroupAttributes & SE_GROUP_ENABLED_BY_DEFAULT) 01252 && !(TokenGroupAttributes & SE_GROUP_ENABLED)); 01253 01254 // 01255 // If the group is disabled by default and currently enabled, 01256 // then we must disable it. 01257 // 01258 01259 DisableGroup = (BOOLEAN)( !(TokenGroupAttributes & SE_GROUP_ENABLED_BY_DEFAULT) 01260 && (TokenGroupAttributes & SE_GROUP_ENABLED)); 01261 01262 // 01263 // Blow up if it's a mandatory group that is not both 01264 // enabled by default and enabled (SepCreateToken should 01265 // make sure that this never happens). 01266 // 01267 01268 ASSERT(!(TokenGroupAttributes & SE_GROUP_MANDATORY) 01269 || (TokenGroupAttributes & (SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED) 01270 == (SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED))); 01271 01272 if ( EnableGroup || DisableGroup ) { 01273 01274 SidLength = SeLengthSid( CurrentGroup.Sid ); 01275 SidLength = (ULONG)LongAlignSize(SidLength); 01276 LocalReturnLength += SidLength; 01277 01278 // 01279 // Change, if necessary (saving previous state if 01280 // appropriate). 01281 // 01282 01283 if (MakeChanges) { 01284 01285 if (ARGUMENT_PRESENT(PreviousState)) { 01286 01287 (*(PreviousState)).Groups[(*ChangeCount)].Attributes = 01288 CurrentGroup.Attributes; 01289 01290 (*(PreviousState)).Groups[(*ChangeCount)].Sid = 01291 NextSid; 01292 01293 RtlCopySid( SidLength, NextSid, CurrentGroup.Sid ); 01294 NextSid = (PSID)((ULONG_PTR)NextSid + SidLength); 01295 } 01296 01297 if (EnableGroup) { 01298 SepTokenGroupAttributes(Token,OldIndex) |= SE_GROUP_ENABLED; 01299 } else { 01300 SepTokenGroupAttributes(Token,OldIndex) &= ~SE_GROUP_ENABLED; 01301 } 01302 01303 01304 01305 } //endif make changes 01306 01307 // 01308 // increment the number of changes 01309 // 01310 01311 (*ChangeCount) += 1; 01312 01313 } // endif group enabled 01314 01315 } else { 01316 01317 // 01318 // Selective adjustments - this is a little trickier 01319 // Compare the current group to each of those in 01320 // the NewState array. If a match is found, then adjust 01321 // the current group appropriately. 01322 // 01323 01324 NewIndex = 0; 01325 Found = FALSE; 01326 01327 while ( (NewIndex < GroupCount) && !Found) { 01328 01329 // 01330 // Look for a comparison 01331 // 01332 01333 if (RtlEqualSid( 01334 CurrentGroup.Sid, 01335 NewState[NewIndex].Sid 01336 ) ) { 01337 01338 Found = TRUE; 01339 MatchCount += 1; 01340 01341 01342 // 01343 // See if it needs to be changed 01344 // 01345 01346 if ( (SepArrayGroupAttributes( NewState, NewIndex ) & 01347 SE_GROUP_ENABLED ) != 01348 (SepTokenGroupAttributes(Token,OldIndex) & 01349 SE_GROUP_ENABLED ) ) { 01350 01351 // 01352 // Make sure group is not mandatory 01353 // 01354 01355 if (SepTokenGroupAttributes(Token,OldIndex) & 01356 SE_GROUP_MANDATORY ) { 01357 return STATUS_CANT_DISABLE_MANDATORY; 01358 } 01359 01360 // 01361 // Make sure group is not deny-only 01362 // 01363 01364 01365 if (SepTokenGroupAttributes(Token,OldIndex) & 01366 SE_GROUP_USE_FOR_DENY_ONLY ) { 01367 return STATUS_CANT_ENABLE_DENY_ONLY; 01368 } 01369 01370 SidLength = SeLengthSid( CurrentGroup.Sid ); 01371 SidLength = (ULONG)LongAlignSize(SidLength); 01372 LocalReturnLength += SidLength; 01373 01374 // 01375 // Change, if necessary (saving previous state if 01376 // appropriate). 01377 // 01378 01379 if (MakeChanges) { 01380 01381 if (ARGUMENT_PRESENT(PreviousState)) { 01382 01383 PreviousState->Groups[(*ChangeCount)].Attributes = 01384 CurrentGroup.Attributes; 01385 01386 PreviousState->Groups[(*ChangeCount)].Sid = 01387 NextSid; 01388 01389 RtlCopySid( SidLength, NextSid, CurrentGroup.Sid ); 01390 01391 NextSid = (PSID)((ULONG_PTR)NextSid + SidLength); 01392 } 01393 01394 SepTokenGroupAttributes(Token,OldIndex) &= 01395 ~(SepTokenGroupAttributes(Token,OldIndex) 01396 & SE_GROUP_ENABLED); 01397 SepTokenGroupAttributes(Token,OldIndex) |= 01398 (SepArrayGroupAttributes(NewState,NewIndex) 01399 & SE_GROUP_ENABLED); 01400 01401 01402 01403 } //endif make changes 01404 01405 // 01406 // increment the number of changes 01407 // 01408 01409 (*ChangeCount) += 1; 01410 01411 01412 } // endif change needed 01413 01414 } // endif found 01415 01416 NewIndex += 1; 01417 01418 } // endwhile searching NewState 01419 01420 } // endelse 01421 01422 OldIndex += 1; 01423 01424 } // endwhile more groups in token 01425 01426 // 01427 // Set completion status appropriately if some not assigned 01428 // 01429 01430 if (!ResetToDefault) { 01431 01432 if (MatchCount < GroupCount) { 01433 CompletionStatus = STATUS_NOT_ALL_ASSIGNED; 01434 } 01435 } 01436 01437 // 01438 // Indicate whether changes were made 01439 // 01440 01441 if ((*ChangeCount) > 0 && MakeChanges) { 01442 (*ChangesMade) = TRUE; 01443 } else { 01444 (*ChangesMade) = FALSE; 01445 } 01446 01447 // 01448 // Calculate the space needed to return previous state information 01449 // (The SID lengths have already been added up in LocalReturnLength). 01450 // 01451 01452 if (ARGUMENT_PRESENT(PreviousState)) { 01453 01454 (*ReturnLength) = LocalReturnLength + 01455 (ULONG)sizeof(TOKEN_GROUPS) + 01456 ((*ChangeCount) * (ULONG)sizeof(SID_AND_ATTRIBUTES)) - 01457 (ANYSIZE_ARRAY * (ULONG)sizeof(SID_AND_ATTRIBUTES)); 01458 } 01459 01460 return CompletionStatus; 01461 } }

NTSTATUS SepAdjustPrivileges IN PTOKEN  Token,
IN BOOLEAN  MakeChanges,
IN BOOLEAN  DisableAllPrivileges,
IN ULONG PrivilegeCount  OPTIONAL,
IN PLUID_AND_ATTRIBUTES NewState  OPTIONAL,
OUT PTOKEN_PRIVILEGES PreviousState  OPTIONAL,
OUT PULONG  ReturnLength,
OUT PULONG  ChangeCount,
OUT PBOOLEAN  ChangesMade
 

Definition at line 819 of file tokenadj.c.

References ANYSIZE_ARRAY, DisableAllPrivileges(), FALSE, NTSTATUS(), PAGED_CODE, RtlEqualLuid(), SeChangeNotifyPrivilege, SepArrayPrivilegeAttributes, SepTokenPrivilegeAttributes, Token, TOKEN_HAS_TRAVERSE_PRIVILEGE, and TRUE.

Referenced by NtAdjustPrivilegesToken().

00834 : 00835 00836 This routine is used to walk the privileges array in a token as a 00837 result of a request to adjust privileges. 00838 00839 If the MakeChanges parameter is FALSE, this routine simply determines 00840 what changes are needed and how much space is necessary to save the 00841 current state of changed privileges. 00842 00843 If the MakeChanges parameter is TRUE, this routine will not only 00844 calculate the space necessary to save the current state, but will 00845 actually make the changes. 00846 00847 This routine makes the following assumptions: 00848 00849 1) The token is locked for exclusive access. 00850 00851 2) The PrivilegeCount and NewState parameters (if passed) are captured 00852 and accesses to them will not result in access violations. 00853 00854 4) Any access violations encountered may leave the request 00855 partially completed. It is the calling routine's responsibility 00856 to catch exceptions. 00857 00858 5) The calling routine is responsible for inrementing the token's 00859 ModifiedId field. 00860 00861 Arguments: 00862 00863 Token - Pointer to the token to act upon. 00864 00865 MakeChanges - A boolean value indicating whether the changes should 00866 actually be made, or just evaluated. A value of TRUE indicates 00867 the changes should be made. 00868 00869 DisableAllPrivilegs - A boolean value indicating whether all privileges 00870 are to be disabled, or only select, specified privileges. A value 00871 of TRUE indicates all privileges are to be disabled. 00872 00873 PrivilegeCount - This parameter is required only if the NewState parameter 00874 is used. In that case, this parameter indicates how many entries are 00875 in the NewState parameter. 00876 00877 NewState - This parameter is ignored if the DisableAllPrivileges 00878 argument is TRUE. If the DisableAllPrivileges argument is FALSE, 00879 then this parameter must be provided and specifies the new state 00880 to set privileges to (enabled or disabled). 00881 00882 PreviousState - This (optional) parameter points to a buffer to 00883 receive the state of any privileges actually changed by this 00884 request. This information is formated as a TOKEN_PRIVILEGES data 00885 structure which may be passed as the NewState parameter in a 00886 subsequent call to NtAdjustPrivileges to restore the original state 00887 of those privileges. It is the caller's responsibility to make 00888 sure this buffer is large enough to receive all the state 00889 information. 00890 00891 ReturnLength - Points to a buffer to receive the number of bytes needed 00892 to retrieve the previous state information of changed privileges. 00893 This parameter is ignored if the PreviousState argument is not 00894 passed. 00895 00896 ChangeCount - Points to a ULONG to receive the number of privileges 00897 which were adjusted (or would be adjusted, if changes are made). 00898 00899 ChangesMade - Points to a boolean flag which is to receive an indication 00900 as to whether any changes were made as a result of this call. This 00901 is expected to be used to decide whether or not to increment the 00902 token's ModifiedId field. 00903 00904 Return Value: 00905 00906 STATUS_SUCCESS - Call completed sccessfully. 00907 00908 STATUS_NOT_ALL_ASSIGNED - Indicates not all the specified adjustments 00909 have been made (or could be made, if update wasn't requested). 00910 00911 --*/ 00912 { 00913 NTSTATUS CompletionStatus = STATUS_SUCCESS; 00914 00915 ULONG OldIndex; 00916 ULONG NewIndex; 00917 BOOLEAN Found; 00918 ULONG MatchCount = 0; 00919 00920 LUID_AND_ATTRIBUTES CurrentPrivilege; 00921 00922 PAGED_CODE(); 00923 00924 // 00925 // Walk through the privileges array to determine which need to be 00926 // adjusted. 00927 // 00928 00929 OldIndex = 0; 00930 (*ChangeCount) = 0; 00931 00932 while (OldIndex < Token->PrivilegeCount) { 00933 00934 CurrentPrivilege = (Token->Privileges)[OldIndex]; 00935 00936 if (DisableAllPrivileges) { 00937 00938 if (SepTokenPrivilegeAttributes(Token,OldIndex) & 00939 SE_PRIVILEGE_ENABLED ) { 00940 00941 // 00942 // Change, if necessary (saving previous state if 00943 // appropriate). 00944 // 00945 00946 if (MakeChanges) { 00947 00948 if (ARGUMENT_PRESENT(PreviousState)) { 00949 00950 PreviousState->Privileges[(*ChangeCount)] = 00951 CurrentPrivilege; 00952 } 00953 00954 SepTokenPrivilegeAttributes(Token,OldIndex) &= 00955 ~SE_PRIVILEGE_ENABLED; 00956 00957 00958 00959 } //endif make changes 00960 00961 // 00962 // increment the number of changes 00963 // 00964 00965 (*ChangeCount) += 1; 00966 00967 } // endif privilege enabled 00968 00969 } else { 00970 00971 // 00972 // Selective adjustments - this is a little trickier 00973 // Compare the current privilege to each of those in 00974 // the NewState array. If a match is found, then adjust 00975 // the current privilege appropriately. 00976 // 00977 00978 NewIndex = 0; 00979 Found = FALSE; 00980 00981 while ( (NewIndex < PrivilegeCount) && !Found) { 00982 00983 // 00984 // Look for a comparison 00985 // 00986 00987 if (RtlEqualLuid(&CurrentPrivilege.Luid,&NewState[NewIndex].Luid)) { 00988 00989 Found = TRUE; 00990 MatchCount += 1; 00991 00992 if ( (SepArrayPrivilegeAttributes( NewState, NewIndex ) & 00993 SE_PRIVILEGE_ENABLED) 00994 != 00995 (SepTokenPrivilegeAttributes(Token,OldIndex) & 00996 SE_PRIVILEGE_ENABLED) ) { 00997 00998 // 00999 // Change, if necessary (saving previous state if 01000 // appropriate). 01001 // 01002 01003 if (MakeChanges) { 01004 01005 if (ARGUMENT_PRESENT(PreviousState)) { 01006 01007 PreviousState->Privileges[(*ChangeCount)] = 01008 CurrentPrivilege; 01009 } 01010 01011 SepTokenPrivilegeAttributes(Token,OldIndex) &= 01012 ~(SepTokenPrivilegeAttributes(Token,OldIndex) 01013 & SE_PRIVILEGE_ENABLED); 01014 SepTokenPrivilegeAttributes(Token,OldIndex) |= 01015 (SepArrayPrivilegeAttributes(NewState,NewIndex) 01016 & SE_PRIVILEGE_ENABLED); 01017 01018 // 01019 // if this is SeChangeNotifyPrivilege, then 01020 // change its corresponding bit in TokenFlags 01021 // 01022 01023 if (RtlEqualLuid(&CurrentPrivilege.Luid, 01024 &SeChangeNotifyPrivilege)) { 01025 Token->TokenFlags ^= TOKEN_HAS_TRAVERSE_PRIVILEGE; 01026 } 01027 01028 01029 01030 } //endif make changes 01031 01032 // 01033 // increment the number of changes 01034 // 01035 01036 (*ChangeCount) += 1; 01037 01038 01039 } // endif change needed 01040 01041 } // endif found 01042 01043 NewIndex += 1; 01044 01045 } // endwhile searching NewState 01046 01047 } // endelse 01048 01049 OldIndex += 1; 01050 01051 } // endwhile privileges in token 01052 01053 // 01054 // If we disabled all privileges, then clear the TokenFlags flag 01055 // corresponding to the SeChangeNotifyPrivilege privilege. 01056 // 01057 01058 01059 if (DisableAllPrivileges) { 01060 Token->TokenFlags &= ~TOKEN_HAS_TRAVERSE_PRIVILEGE; 01061 } 01062 01063 // 01064 // Set completion status appropriately if some not assigned 01065 // 01066 01067 if (!DisableAllPrivileges) { 01068 01069 if (MatchCount < PrivilegeCount) { 01070 CompletionStatus = STATUS_NOT_ALL_ASSIGNED; 01071 } 01072 } 01073 01074 // 01075 // Indicate whether changes were made 01076 // 01077 01078 if ((*ChangeCount) > 0 && MakeChanges) { 01079 (*ChangesMade) = TRUE; 01080 } else { 01081 (*ChangesMade) = FALSE; 01082 } 01083 01084 // 01085 // Calculate the space needed to return previous state information 01086 // 01087 01088 if (ARGUMENT_PRESENT(PreviousState)) { 01089 01090 (*ReturnLength) = (ULONG)sizeof(TOKEN_PRIVILEGES) + 01091 ((*ChangeCount) * (ULONG)sizeof(LUID_AND_ATTRIBUTES)) - 01092 (ANYSIZE_ARRAY * (ULONG)sizeof(LUID_AND_ATTRIBUTES)); 01093 } 01094 01095 return CompletionStatus; 01096 }

VOID SepAppendDefaultDacl IN PTOKEN  Token,
IN PACL  PAcl
 

Definition at line 778 of file tokenset.c.

References ASSERT, PAGED_CODE, SeLengthSid, and Token.

Referenced by NtSetInformationToken().

00786 : 00787 00788 Add a default discretionary ACL to the available space at the end of the 00789 dynamic part of the token. It is the caller's responsibility to ensure 00790 that the default Dacl fits within the available space of the dynamic 00791 part of the token. 00792 00793 The token is assumed to be locked for write access before calling 00794 this routine. 00795 00796 Arguments: 00797 00798 Token - Pointer to the token. 00799 00800 PAcl - Pointer to the ACL to add. 00801 00802 Return Value: 00803 00804 None. 00805 00806 --*/ 00807 { 00808 ULONG_PTR NextFree; 00809 ULONG AclSize; 00810 00811 PAGED_CODE(); 00812 00813 // 00814 // Add the size of the primary group to the 00815 // address of the Dynamic Part of the token to establish 00816 // where the primary group should be placed. 00817 // 00818 00819 ASSERT(ARGUMENT_PRESENT(Token->PrimaryGroup)); 00820 00821 NextFree = (ULONG_PTR)(Token->DynamicPart) + SeLengthSid(Token->PrimaryGroup); 00822 00823 // 00824 // Now copy the default Dacl 00825 // 00826 00827 AclSize = (ULONG)(PAcl->AclSize); 00828 // ASSERT(AclSize == (ULONG)LongAlignSize(AclSize)); 00829 00830 RtlCopyMemory( 00831 (PVOID)NextFree, 00832 (PVOID)PAcl, 00833 AclSize 00834 ); 00835 00836 Token->DefaultDacl = (PACL)NextFree; 00837 00838 // 00839 // And decrement the amount of the dynamic part that is available. 00840 // 00841 00842 ASSERT( AclSize <= (Token->DynamicAvailable) ); 00843 Token->DynamicAvailable -= AclSize; 00844 00845 return; 00846 00847 }

VOID SepAppendPrimaryGroup IN PTOKEN  Token,
IN PSID  PSid
 

Definition at line 697 of file tokenset.c.

References ASSERT, PAGED_CODE, SeLengthSid, and Token.

Referenced by NtSetInformationToken().

00705 : 00706 00707 Add a primary group SID to the available space at the end of the dynamic 00708 part of the token. It is the caller's responsibility to ensure that the 00709 primary group SID fits within the available space of the dynamic part of 00710 the token. 00711 00712 The token is assumed to be locked for write access before calling 00713 this routine. 00714 00715 Arguments: 00716 00717 Token - Pointer to the token. 00718 00719 PSid - Pointer to the SID to add. 00720 00721 Return Value: 00722 00723 None. 00724 00725 --*/ 00726 { 00727 ULONG_PTR NextFree; 00728 ULONG SidSize; 00729 00730 PAGED_CODE(); 00731 00732 // 00733 // Add the size of the Default Dacl (if there is one) to the 00734 // address of the Dynamic Part of the token to establish 00735 // where the primary group should be placed. 00736 // 00737 00738 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00739 00740 // ASSERT( (ULONG)(Token->DefaultDacl->AclSize) == 00741 // (ULONG)LongAlignSize(Token->DefaultDacl->AclSize) ); 00742 00743 NextFree = (ULONG_PTR)(Token->DynamicPart) + Token->DefaultDacl->AclSize; 00744 00745 } else { 00746 00747 NextFree = (ULONG_PTR)(Token->DynamicPart); 00748 00749 } 00750 00751 // 00752 // Now copy the primary group SID. 00753 // 00754 00755 00756 SidSize = SeLengthSid( PSid ); 00757 00758 RtlCopyMemory( 00759 (PVOID)NextFree, 00760 (PVOID)PSid, 00761 SidSize 00762 ); 00763 00764 Token->PrimaryGroup = (PSID)NextFree; 00765 00766 // 00767 // And decrement the amount of the dynamic part that is available. 00768 // 00769 00770 ASSERT( SidSize <= (Token->DynamicAvailable) ); 00771 Token->DynamicAvailable -= SidSize; 00772 00773 return; 00774 00775 }

NTSTATUS SepDuplicateToken IN PTOKEN  ExistingToken,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
IN BOOLEAN  EffectiveOnly,
IN TOKEN_TYPE  TokenType,
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel  OPTIONAL,
IN KPROCESSOR_MODE  RequestorMode,
OUT PTOKEN DuplicateToken
 

Definition at line 362 of file tokendup.c.

References ASSERT, DbgPrint, ExAllocateLocallyUniqueId, ExAllocatePool, ExAllocatePoolWithTag, ExFreePool(), FALSE, Index, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObjectAttributes, PAGED_CODE, PagedPool, PTOKEN, SepAcquireTokenReadLock, SepCopyProxyData(), SepDeReferenceLogonSession(), SepFreeProxyData(), SepMakeTokenEffectiveOnly(), SepReferenceLogonSession(), SepReleaseTokenReadLock, SepTokenObjectType, and Status.

Referenced by NtDuplicateToken(), NtOpenThreadToken(), SeCopyClientToken(), and SeSubProcessToken().

00376 : 00377 00378 This routine does the bulk of the work to actually duplicate 00379 a token. This routine assumes all access validation and argument 00380 probing (except the ObjectAttributes) has been performed. 00381 00382 THE CALLER IS RESPONSIBLE FOR CHECKING SUBJECT RIGHTS TO CREATE THE 00383 TYPE OF TOKEN BEING CREATED. 00384 00385 This routine acquires a read lock on the token being duplicated. 00386 00387 Arguments: 00388 00389 ExistingToken - Points to the token to be duplicated. 00390 00391 ObjectAttributes - Points to the standard object attributes data 00392 structure. Refer to the NT Object Management 00393 Specification for a description of this data structure. 00394 00395 The security Quality Of Service of the object attributes are ignored. 00396 This information must be specified using parameters to this 00397 routine. 00398 00399 EffectiveOnly - Is a boolean flag indicating whether the entire 00400 source token should be duplicated into the target token or 00401 just the effective (currently enabled) part of the token. 00402 This provides a means for a caller of a protected subsystem 00403 to limit which privileges and optional groups are made 00404 available to the protected subsystem. A value of TRUE 00405 indicates only the currently enabled parts of the source 00406 token are to be duplicated. Otherwise, the entire source 00407 token is duplicated. 00408 00409 TokenType - Indicates the type of token to make the duplicate token. 00410 00411 ImpersonationLevel - This value specifies the impersonation level 00412 to assign to the duplicate token. If the TokenType of the 00413 duplicate is not TokenImpersonation then this parameter is 00414 ignored. Otherwise, it is must be provided. 00415 00416 RequestorMode - Mode of client requesting the token be duplicated. 00417 00418 DuplicateToken - Receives a pointer to the duplicate token. 00419 The token has not yet been inserted into any object table. 00420 No exceptions are expected when tring to set this OUT value. 00421 00422 Return Value: 00423 00424 STATUS_SUCCESS - The service successfully completed the requested 00425 operation. 00426 00427 00428 --*/ 00429 { 00430 NTSTATUS Status; 00431 00432 PTOKEN NewToken; 00433 PULONG DynamicPart; 00434 ULONG PagedPoolSize; 00435 ULONG NonPagedPoolSize; 00436 ULONG TokenBodyLength; 00437 ULONG FieldOffset; 00438 00439 ULONG Index; 00440 00441 PSECURITY_TOKEN_PROXY_DATA NewProxyData; 00442 PSECURITY_TOKEN_AUDIT_DATA NewAuditData; 00443 00444 00445 PAGED_CODE(); 00446 00447 ASSERT( sizeof(SECURITY_IMPERSONATION_LEVEL) <= sizeof(ULONG) ); 00448 00449 00450 if ( TokenType == TokenImpersonation ) { 00451 00452 ASSERT( SecurityDelegation > SecurityImpersonation ); 00453 ASSERT( SecurityImpersonation > SecurityIdentification ); 00454 ASSERT( SecurityIdentification > SecurityAnonymous ); 00455 00456 if ( (ImpersonationLevel > SecurityDelegation) || 00457 (ImpersonationLevel < SecurityAnonymous) ) { 00458 00459 return STATUS_BAD_IMPERSONATION_LEVEL; 00460 } 00461 } 00462 00463 00464 // 00465 // Increment the reference count for this logon session 00466 // This can not fail, since there is already a token in this logon 00467 // session. 00468 // 00469 00470 Status = SepReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 00471 ASSERT( NT_SUCCESS(Status) ); 00472 00473 00474 00475 // 00476 // Note that the size of the dynamic portion of a token can not change 00477 // once established. 00478 // 00479 00480 // 00481 // Allocate the dynamic portion 00482 // 00483 00484 DynamicPart = (PULONG)ExAllocatePoolWithTag( 00485 PagedPool, 00486 ExistingToken->DynamicCharged, 00487 'dTeS' 00488 ); 00489 00490 if (DynamicPart == NULL) { 00491 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 00492 return( STATUS_INSUFFICIENT_RESOURCES ); 00493 } 00494 00495 if (ARGUMENT_PRESENT(ExistingToken->ProxyData)) { 00496 00497 Status = SepCopyProxyData( 00498 &NewProxyData, 00499 ExistingToken->ProxyData 00500 ); 00501 00502 if (!NT_SUCCESS(Status)) { 00503 00504 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 00505 ExFreePool( DynamicPart ); 00506 return( Status ); 00507 } 00508 00509 } else { 00510 00511 NewProxyData = NULL; 00512 } 00513 00514 if (ARGUMENT_PRESENT( ExistingToken->AuditData )) { 00515 00516 NewAuditData = ExAllocatePool( PagedPool, sizeof( SECURITY_TOKEN_AUDIT_DATA )); 00517 00518 if (NewAuditData == NULL) { 00519 00520 SepFreeProxyData( NewProxyData ); 00521 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 00522 ExFreePool( DynamicPart ); 00523 00524 return( STATUS_INSUFFICIENT_RESOURCES ); 00525 00526 } else { 00527 00528 *NewAuditData = *(ExistingToken->AuditData); 00529 } 00530 00531 } else { 00532 00533 NewAuditData = NULL; 00534 00535 } 00536 00537 // 00538 // Create a new object 00539 // 00540 00541 TokenBodyLength = (ULONG)sizeof(TOKEN) + 00542 ExistingToken->VariableLength; 00543 00544 NonPagedPoolSize = TokenBodyLength; 00545 PagedPoolSize = ExistingToken->DynamicCharged; 00546 00547 Status = ObCreateObject( 00548 RequestorMode, // ProbeMode 00549 SepTokenObjectType, // ObjectType 00550 ObjectAttributes, // ObjectAttributes 00551 RequestorMode, // OwnershipMode 00552 NULL, // ParseContext 00553 TokenBodyLength, // ObjectBodySize 00554 PagedPoolSize, // PagedPoolCharge 00555 NonPagedPoolSize, // NonPagedPoolCharge 00556 (PVOID *)&NewToken // Return pointer to object 00557 ); 00558 00559 if (!NT_SUCCESS(Status)) { 00560 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 00561 ExFreePool( DynamicPart ); 00562 SepFreeProxyData( NewProxyData ); 00563 00564 if (NewAuditData != NULL) { 00565 ExFreePool( NewAuditData ); 00566 } 00567 00568 return Status; 00569 } 00570 00571 00572 // 00573 // acquire exclusive access to the source token 00574 // 00575 00576 SepAcquireTokenReadLock( ExistingToken ); 00577 00578 00579 // 00580 // Main Body initialization 00581 // 00582 00583 // 00584 // The following fields are unchanged from the source token. 00585 // Although some may change if EffectiveOnly has been specified. 00586 // 00587 00588 NewToken->AuthenticationId = ExistingToken->AuthenticationId; 00589 NewToken->ModifiedId = ExistingToken->ModifiedId; 00590 NewToken->ExpirationTime = ExistingToken->ExpirationTime; 00591 NewToken->TokenSource = ExistingToken->TokenSource; 00592 NewToken->DynamicCharged = ExistingToken->DynamicCharged; 00593 NewToken->DynamicAvailable = ExistingToken->DynamicAvailable; 00594 NewToken->DefaultOwnerIndex = ExistingToken->DefaultOwnerIndex; 00595 NewToken->UserAndGroupCount = ExistingToken->UserAndGroupCount; 00596 NewToken->RestrictedSidCount = ExistingToken->RestrictedSidCount; 00597 NewToken->PrivilegeCount = ExistingToken->PrivilegeCount; 00598 NewToken->VariableLength = ExistingToken->VariableLength; 00599 NewToken->TokenFlags = ExistingToken->TokenFlags; 00600 NewToken->ProxyData = NewProxyData; 00601 NewToken->AuditData = NewAuditData; 00602 NewToken->SessionId = ExistingToken->SessionId; 00603 00604 00605 // 00606 // The following fields differ in the new token. 00607 // 00608 00609 ExAllocateLocallyUniqueId( &(NewToken->TokenId) ); 00610 NewToken->ParentTokenId = ExistingToken->ParentTokenId; 00611 NewToken->TokenInUse = FALSE; 00612 NewToken->TokenType = TokenType; 00613 NewToken->ImpersonationLevel = ImpersonationLevel; 00614 00615 00616 // 00617 // Copy and initialize the variable part. 00618 // The variable part is assumed to be position independent. 00619 // 00620 00621 RtlCopyMemory( (PVOID)&(NewToken->VariablePart), 00622 (PVOID)&(ExistingToken->VariablePart), 00623 ExistingToken->VariableLength 00624 ); 00625 00626 // 00627 // Set the address of the UserAndGroups array. 00628 // 00629 00630 ASSERT( ARGUMENT_PRESENT(ExistingToken->UserAndGroups ) ); 00631 ASSERT( (ULONG_PTR)(ExistingToken->UserAndGroups) >= 00632 (ULONG_PTR)(&(ExistingToken->VariablePart)) ); 00633 00634 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->UserAndGroups) - 00635 (ULONG_PTR)(&(ExistingToken->VariablePart))); 00636 00637 NewToken->UserAndGroups = 00638 (PSID_AND_ATTRIBUTES)(FieldOffset + (ULONG_PTR)(&(NewToken->VariablePart))); 00639 00640 // 00641 // Now go through and change the address of each SID pointer 00642 // for the user and groups 00643 // 00644 00645 Index = 0; 00646 00647 while (Index < ExistingToken->UserAndGroupCount) { 00648 00649 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->UserAndGroups[Index].Sid) - 00650 (ULONG_PTR)(&(ExistingToken->VariablePart))); 00651 00652 NewToken->UserAndGroups[Index].Sid = 00653 (PSID)( FieldOffset + (ULONG_PTR)(&(NewToken->VariablePart)) ); 00654 00655 Index += 1; 00656 00657 } 00658 00659 // 00660 // Set the address of the RestrictedSids array. 00661 // 00662 00663 if (ARGUMENT_PRESENT(ExistingToken->RestrictedSids ) ) { 00664 ASSERT( (ULONG_PTR)(ExistingToken->RestrictedSids) >= 00665 (ULONG_PTR)(&(ExistingToken->VariablePart)) ); 00666 00667 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->RestrictedSids) - 00668 (ULONG_PTR)(&(ExistingToken->VariablePart))); 00669 00670 NewToken->RestrictedSids = 00671 (PSID_AND_ATTRIBUTES)(FieldOffset + (ULONG_PTR)(&(NewToken->VariablePart)) ); 00672 00673 // 00674 // Now go through and change the address of each SID pointer 00675 // for the user and groups 00676 // 00677 00678 Index = 0; 00679 00680 while (Index < ExistingToken->RestrictedSidCount) { 00681 00682 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->RestrictedSids[Index].Sid) - 00683 (ULONG_PTR)(&(ExistingToken->VariablePart))); 00684 00685 NewToken->RestrictedSids[Index].Sid = 00686 (PSID)( FieldOffset + (ULONG_PTR)(&(NewToken->VariablePart)) ); 00687 00688 Index += 1; 00689 00690 } 00691 } else { 00692 NewToken->RestrictedSids = NULL; 00693 } 00694 00695 00696 // 00697 // If present, set the address of the privileges 00698 // 00699 00700 if (ExistingToken->PrivilegeCount > 0) { 00701 ASSERT( ARGUMENT_PRESENT(ExistingToken->Privileges ) ); 00702 ASSERT( (ULONG_PTR)(ExistingToken->Privileges) >= 00703 (ULONG_PTR)(&(ExistingToken->VariablePart)) ); 00704 00705 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->Privileges) - 00706 (ULONG_PTR)(&(ExistingToken->VariablePart))); 00707 NewToken->Privileges = (PLUID_AND_ATTRIBUTES)( 00708 FieldOffset + 00709 (ULONG_PTR)(&(NewToken->VariablePart)) 00710 ); 00711 } else { 00712 00713 NewToken->Privileges = NULL; 00714 00715 } 00716 00717 // 00718 // Copy and initialize the dynamic part. 00719 // The dynamic part is assumed to be position independent. 00720 // 00721 00722 RtlCopyMemory( (PVOID)DynamicPart, 00723 (PVOID)(ExistingToken->DynamicPart), 00724 ExistingToken->DynamicCharged 00725 ); 00726 00727 NewToken->DynamicPart = DynamicPart; 00728 00729 // 00730 // If present, set the address of the default Dacl 00731 // 00732 00733 if (ARGUMENT_PRESENT(ExistingToken->DefaultDacl)) { 00734 00735 ASSERT( (ULONG_PTR)(ExistingToken->DefaultDacl) >= 00736 (ULONG_PTR)(ExistingToken->DynamicPart) ); 00737 00738 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->DefaultDacl) - 00739 (ULONG_PTR)(ExistingToken->DynamicPart)); 00740 00741 NewToken->DefaultDacl = (PACL)(FieldOffset + (ULONG_PTR)DynamicPart); 00742 00743 } else { 00744 00745 NewToken->DefaultDacl = NULL; 00746 } 00747 00748 00749 // 00750 // Set the address of the primary group 00751 // 00752 00753 ASSERT(ARGUMENT_PRESENT(ExistingToken->PrimaryGroup)); 00754 00755 ASSERT( (ULONG_PTR)(ExistingToken->PrimaryGroup) >= 00756 (ULONG_PTR)(ExistingToken->DynamicPart) ); 00757 00758 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->PrimaryGroup) - 00759 (ULONG_PTR)(ExistingToken->DynamicPart)); 00760 00761 NewToken->PrimaryGroup = (PACL)(FieldOffset + (ULONG_PTR)(DynamicPart)); 00762 00763 00764 // 00765 // For the time being, take the easy way to generating an "EffectiveOnly" 00766 // duplicate. That is, use the same space required of the original, just 00767 // eliminate any IDs or privileges not active. 00768 // 00769 // Ultimately, if duplication becomes a common operation, then it will be 00770 // worthwhile to recalculate the actual space needed and copy only the 00771 // effective IDs/privileges into the new token. 00772 // 00773 00774 if (EffectiveOnly) { 00775 SepMakeTokenEffectiveOnly( NewToken ); 00776 } 00777 00778 00779 #ifdef TOKEN_DEBUG 00780 00781 // 00782 // Debug 00783 DbgPrint("\n"); 00784 DbgPrint("\n"); 00785 DbgPrint("\n"); 00786 DbgPrint("Duplicate token:\n"); 00787 SepDumpToken( NewToken ); 00788 // Debug 00789 // 00791 #endif //TOKEN_DEBUG 00792 00793 // 00794 // Release the source token. 00795 // 00796 00797 SepReleaseTokenReadLock( ExistingToken ); 00798 00799 00800 (*DuplicateToken) = NewToken; 00801 return Status; 00802 }

NTSTATUS SepFilterToken IN PTOKEN  ExistingToken,
IN KPROCESSOR_MODE  RequestorMode,
IN ULONG  Flags,
IN ULONG  GroupCount,
IN PSID_AND_ATTRIBUTES GroupsToDisable  OPTIONAL,
IN ULONG  PrivilegeCount,
IN PLUID_AND_ATTRIBUTES PrivilegesToDelete  OPTIONAL,
IN ULONG  SidCount,
IN PSID_AND_ATTRIBUTES RestrictedSids  OPTIONAL,
IN ULONG  SidLength,
OUT PTOKEN FilteredToken
 

Definition at line 1939 of file tokendup.c.

References ASSERT, DbgPrint, ExAllocateLocallyUniqueId, ExAllocatePool, ExAllocatePoolWithTag, ExFreePool(), FALSE, Index, MAX, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObject(), ObDereferenceObject, PAGED_CODE, PagedPool, PTOKEN, RtlCopyLuidAndAttributesArray(), RtlCopySidAndAttributesArray(), SepAcquireTokenReadLock, SepCopyProxyData(), SepDeReferenceLogonSession(), SepFreeProxyData(), SepReferenceLogonSession(), SepReleaseTokenReadLock, SepRemoveDisabledGroupsAndPrivileges(), SepSidInSidAndAttributes(), SepTokenObjectType, Status, and TOKEN_IS_RESTRICTED.

Referenced by NtFilterToken(), SeFastFilterToken(), and SeFilterToken().

01955 : 01956 01957 This routine does the bulk of the work to actually filter 01958 a token. This routine assumes all access validation and argument 01959 probing has been performed. 01960 01961 THE CALLER IS RESPONSIBLE FOR CHECKING SUBJECT RIGHTS TO CREATE THE 01962 TYPE OF TOKEN BEING CREATED. 01963 01964 This routine acquires a read lock on the token being filtered. 01965 01966 Arguments: 01967 01968 ExistingToken - Points to the token to be duplicated. 01969 01970 RequestorMode - Mode of client requesting the token be duplicated. 01971 01972 GroupCount - Count of groups to disable 01973 01974 GroupsToDisable - Contains a list of sids and attributes. All sids with 01975 the USE_FOR_DENY_ONLY attribute that also exist in the token will 01976 cause the new token to have that sid set with the USE_FOR_DENY_ONLY 01977 attribute. 01978 01979 PrivilegeCount - Count of privileges to delete 01980 01981 PrivilegesToDelete - Privileges in this list that are present in the 01982 existing token will not exist in the final token. This is similar 01983 to duplicating a token effective only with these privileges set to 01984 disabled. 01985 01986 SidCount - Count of restricted sids to add. 01987 01988 RestrictedSids - Contains a list of SIDs and attributes that will be 01989 stored in the RestrictedSids field of the new token. These SIDs 01990 are used after a normal access check to futher restrict access. 01991 The attributes of these groups are always SE_GROUP_MANDATORY | 01992 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT. If there already 01993 exist RestrictedSids in the original token, the intersection of the 01994 two sets will be in the final tokense sids will be. 01995 01996 SidLength - Length of added restricted sids. 01997 01998 FilteredToken - Receives a pointer to the duplicate token. 01999 The token has not yet been inserted into any object table. 02000 No exceptions are expected when tring to set this OUT value. 02001 02002 Return Value: 02003 02004 STATUS_SUCCESS - The service successfully completed the requested 02005 operation. 02006 02007 02008 --*/ 02009 { 02010 NTSTATUS Status; 02011 02012 PTOKEN NewToken; 02013 PULONG DynamicPart; 02014 ULONG PagedPoolSize; 02015 ULONG NonPagedPoolSize; 02016 ULONG TokenBodyLength; 02017 ULONG FieldOffset; 02018 ULONG_PTR NextFree; 02019 PSID NextSidFree; 02020 ULONG VariableLength; 02021 02022 ULONG Index; 02023 02024 PSECURITY_TOKEN_PROXY_DATA NewProxyData; 02025 PSECURITY_TOKEN_AUDIT_DATA NewAuditData; 02026 OBJECT_ATTRIBUTES ObjA ; 02027 02028 02029 PAGED_CODE(); 02030 02031 ASSERT( sizeof(SECURITY_IMPERSONATION_LEVEL) <= sizeof(ULONG) ); 02032 02033 02034 // 02035 // Increment the reference count for this logon session 02036 // This can not fail, since there is already a token in this logon 02037 // session. 02038 // 02039 02040 Status = SepReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 02041 ASSERT( NT_SUCCESS(Status) ); 02042 02043 02044 02045 // 02046 // Note that the size of the dynamic portion of a token can not change 02047 // once established. 02048 // 02049 02050 // 02051 // Allocate the dynamic portion 02052 // 02053 02054 DynamicPart = (PULONG)ExAllocatePoolWithTag( 02055 PagedPool, 02056 ExistingToken->DynamicCharged, 02057 'dTeS' 02058 ); 02059 02060 if (DynamicPart == NULL) { 02061 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 02062 return( STATUS_INSUFFICIENT_RESOURCES ); 02063 } 02064 02065 if (ARGUMENT_PRESENT(ExistingToken->ProxyData)) { 02066 02067 Status = SepCopyProxyData( 02068 &NewProxyData, 02069 ExistingToken->ProxyData 02070 ); 02071 02072 if (!NT_SUCCESS(Status)) { 02073 02074 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 02075 ExFreePool( DynamicPart ); 02076 return( Status ); 02077 } 02078 02079 } else { 02080 02081 NewProxyData = NULL; 02082 } 02083 02084 if (ARGUMENT_PRESENT( ExistingToken->AuditData )) { 02085 02086 NewAuditData = ExAllocatePool( PagedPool, sizeof( SECURITY_TOKEN_AUDIT_DATA )); 02087 02088 if (NewAuditData == NULL) { 02089 02090 SepFreeProxyData( NewProxyData ); 02091 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 02092 ExFreePool( DynamicPart ); 02093 02094 return( STATUS_INSUFFICIENT_RESOURCES ); 02095 02096 } else { 02097 02098 *NewAuditData = *(ExistingToken->AuditData); 02099 } 02100 02101 } else { 02102 02103 NewAuditData = NULL; 02104 02105 } 02106 02107 // 02108 // Create a new object 02109 // 02110 02111 VariableLength = ExistingToken->VariableLength + SidLength; 02112 02113 TokenBodyLength = (ULONG)sizeof(TOKEN) + 02114 VariableLength; 02115 02116 NonPagedPoolSize = TokenBodyLength; 02117 PagedPoolSize = ExistingToken->DynamicCharged; 02118 02119 InitializeObjectAttributes( &ObjA, NULL, 0, NULL, NULL ); 02120 02121 Status = ObCreateObject( 02122 RequestorMode, // ProbeMode 02123 SepTokenObjectType, // ObjectType 02124 NULL, // ObjectAttributes 02125 RequestorMode, // OwnershipMode 02126 NULL, // ParseContext 02127 TokenBodyLength, // ObjectBodySize 02128 PagedPoolSize, // PagedPoolCharge 02129 NonPagedPoolSize, // NonPagedPoolCharge 02130 (PVOID *)&NewToken // Return pointer to object 02131 ); 02132 02133 if (!NT_SUCCESS(Status)) { 02134 SepDeReferenceLogonSession( &(ExistingToken->AuthenticationId) ); 02135 ExFreePool( DynamicPart ); 02136 SepFreeProxyData( NewProxyData ); 02137 02138 if (NewAuditData != NULL) { 02139 ExFreePool( NewAuditData ); 02140 } 02141 02142 return Status; 02143 } 02144 02145 02146 // 02147 // acquire exclusive access to the source token 02148 // 02149 02150 SepAcquireTokenReadLock( ExistingToken ); 02151 02152 02153 // 02154 // Main Body initialization 02155 // 02156 02157 // 02158 // The following fields are unchanged from the source token. 02159 // Although some may change if EffectiveOnly has been specified. 02160 // 02161 02162 NewToken->AuthenticationId = ExistingToken->AuthenticationId; 02163 NewToken->ExpirationTime = ExistingToken->ExpirationTime; 02164 NewToken->TokenSource = ExistingToken->TokenSource; 02165 NewToken->DynamicCharged = ExistingToken->DynamicCharged; 02166 NewToken->DynamicAvailable = ExistingToken->DynamicAvailable; 02167 NewToken->DefaultOwnerIndex = ExistingToken->DefaultOwnerIndex; 02168 NewToken->UserAndGroupCount = ExistingToken->UserAndGroupCount; 02169 NewToken->SessionId = ExistingToken->SessionId; 02170 NewToken->RestrictedSidCount = 0; 02171 NewToken->PrivilegeCount = ExistingToken->PrivilegeCount; 02172 NewToken->VariableLength = VariableLength; 02173 NewToken->TokenFlags = ExistingToken->TokenFlags; 02174 NewToken->ProxyData = NewProxyData; 02175 NewToken->AuditData = NewAuditData; 02176 02177 02178 // 02179 // The following fields differ in the new token. 02180 // 02181 02182 // 02183 // Allocate a new modified Id to distinguish this token from the orignial 02184 // token. 02185 // 02186 02187 ExAllocateLocallyUniqueId( &(NewToken->ModifiedId) ); 02188 ExAllocateLocallyUniqueId( &(NewToken->TokenId) ); 02189 NewToken->ParentTokenId = ExistingToken->TokenId; 02190 NewToken->TokenInUse = FALSE; 02191 NewToken->TokenType = ExistingToken->TokenType; 02192 NewToken->ImpersonationLevel = ExistingToken->ImpersonationLevel; 02193 02194 02195 02196 // 02197 // Compute the beginning portion of the variable part, which contains the 02198 // sid & attributes arrays and the privilege set. 02199 // 02200 02201 // 02202 // First copy the privileges. We will later remove the ones that are 02203 // to be deleted. 02204 // 02205 02206 NextFree = (ULONG_PTR)(&NewToken->VariablePart); 02207 NewToken->Privileges = (PLUID_AND_ATTRIBUTES)NextFree; 02208 RtlCopyLuidAndAttributesArray( ExistingToken->PrivilegeCount, 02209 ExistingToken->Privileges, 02210 (PLUID_AND_ATTRIBUTES)NextFree 02211 ); 02212 02213 NextFree += (ExistingToken->PrivilegeCount * (ULONG)sizeof(LUID_AND_ATTRIBUTES)); 02214 VariableLength -= ( (ExistingToken->PrivilegeCount * (ULONG)sizeof(LUID_AND_ATTRIBUTES)) ); 02215 02216 // 02217 // Figure out the count of SIDs. This is the count of users&groups + 02218 // the number of existing restricuted SIDs plus the number of new 02219 // restricted Sids 02220 // 02221 02222 #define MAX(_x_,_y_) ((_x_) > (_y_) ? (_x_) : (_y_)) 02223 02224 NextSidFree = (PSID) (NextFree + (ExistingToken->UserAndGroupCount + 02225 MAX(ExistingToken->RestrictedSidCount,SidCount)) * sizeof(SID_AND_ATTRIBUTES)); 02226 02227 NewToken->UserAndGroups = (PSID_AND_ATTRIBUTES) NextFree; 02228 02229 // 02230 // Copy in the existing users & groups. We will later flag the ones 02231 // to be disabled. 02232 // 02233 02234 Status = RtlCopySidAndAttributesArray( 02235 ExistingToken->UserAndGroupCount, 02236 ExistingToken->UserAndGroups, 02237 VariableLength, 02238 (PSID_AND_ATTRIBUTES)NextFree, 02239 NextSidFree, 02240 &NextSidFree, 02241 &VariableLength 02242 ); 02243 02244 02245 ASSERT(NT_SUCCESS(Status)); 02246 NextFree += (ExistingToken->UserAndGroupCount * (ULONG)sizeof(SID_AND_ATTRIBUTES)); 02247 02248 // 02249 // Now add all the existing restricted sids. We need to take the 02250 // intersection of the two sets. 02251 // 02252 02253 NewToken->RestrictedSids = (PSID_AND_ATTRIBUTES) NextFree; 02254 02255 02256 for (Index = 0; Index < SidCount ; Index++ ) { 02257 if ( ( ExistingToken->RestrictedSidCount == 0 ) || 02258 SepSidInSidAndAttributes( 02259 ExistingToken->RestrictedSids, 02260 ExistingToken->RestrictedSidCount, 02261 NULL, // no self sid 02262 RestrictedSids[Index].Sid 02263 )) { 02264 02265 Status = RtlCopySidAndAttributesArray( 02266 1, 02267 &RestrictedSids[Index], 02268 VariableLength, 02269 (PSID_AND_ATTRIBUTES)NextFree, 02270 NextSidFree, 02271 &NextSidFree, 02272 &VariableLength 02273 ); 02274 ASSERT(NT_SUCCESS(Status)); 02275 NextFree += sizeof(SID_AND_ATTRIBUTES); 02276 NewToken->RestrictedSids[NewToken->RestrictedSidCount].Attributes = 02277 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY; 02278 NewToken->RestrictedSidCount++; 02279 02280 } 02281 } 02282 02283 // 02284 // Make sure the new token has some restrictions. 02285 // If it doesn't, then we've ended up with a token 02286 // that gives us more access than the original, 02287 // which we don't want. 02288 // 02289 02290 if ((ExistingToken->RestrictedSidCount != 0) && 02291 (NewToken->RestrictedSidCount == 0)) { 02292 02293 SepReleaseTokenReadLock( ExistingToken ); 02294 02295 Status = STATUS_INVALID_PARAMETER; 02296 02297 // 02298 // Cleanup. ObDereferenceObject will cause the logon 02299 // session to be dereferenced, and will free the proxy data 02300 // as well as the audit data. 02301 // 02302 // See SepTokenDeleteMethod(), which is called by 02303 // the object manager when the token object is 02304 // being freed. 02305 // 02306 02307 ExFreePool( DynamicPart ); 02308 02309 // 02310 // Do this so we don't crash trying to free whatever 02311 // junk is pointed to by DynamicPart. 02312 // 02313 02314 NewToken->DynamicPart = NULL; 02315 02316 ObDereferenceObject( NewToken ); 02317 02318 return(Status); 02319 } 02320 02321 // 02322 // If there are any restricted sids in the token, turn on the restricted 02323 // flag 02324 // 02325 02326 if (NewToken->RestrictedSidCount > 0) { 02327 NewToken->TokenFlags |= TOKEN_IS_RESTRICTED; 02328 } 02329 02330 // 02331 // Copy and initialize the dynamic part. 02332 // The dynamic part is assumed to be position independent. 02333 // 02334 02335 RtlCopyMemory( (PVOID)DynamicPart, 02336 (PVOID)(ExistingToken->DynamicPart), 02337 ExistingToken->DynamicCharged 02338 ); 02339 02340 NewToken->DynamicPart = DynamicPart; 02341 02342 // 02343 // If present, set the address of the default Dacl 02344 // 02345 02346 if (ARGUMENT_PRESENT(ExistingToken->DefaultDacl)) { 02347 02348 ASSERT( (ULONG_PTR)(ExistingToken->DefaultDacl) >= 02349 (ULONG_PTR)(ExistingToken->DynamicPart) ); 02350 02351 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->DefaultDacl) - 02352 (ULONG_PTR)(ExistingToken->DynamicPart)); 02353 02354 NewToken->DefaultDacl = (PACL)(FieldOffset + (ULONG_PTR)DynamicPart); 02355 02356 } else { 02357 02358 NewToken->DefaultDacl = NULL; 02359 } 02360 02361 02362 // 02363 // Set the address of the primary group 02364 // 02365 02366 ASSERT(ARGUMENT_PRESENT(ExistingToken->PrimaryGroup)); 02367 02368 ASSERT( (ULONG_PTR)(ExistingToken->PrimaryGroup) >= 02369 (ULONG_PTR)(ExistingToken->DynamicPart) ); 02370 02371 FieldOffset = (ULONG)((ULONG_PTR)(ExistingToken->PrimaryGroup) - 02372 (ULONG_PTR)(ExistingToken->DynamicPart)); 02373 02374 NewToken->PrimaryGroup = (PACL)(FieldOffset + (ULONG_PTR)(DynamicPart)); 02375 02376 02377 // 02378 // For the time being, take the easy way to generating an "EffectiveOnly" 02379 // duplicate. That is, use the same space required of the original, just 02380 // eliminate any IDs or privileges not active. 02381 // 02382 // Ultimately, if duplication becomes a common operation, then it will be 02383 // worthwhile to recalculate the actual space needed and copy only the 02384 // effective IDs/privileges into the new token. 02385 // 02386 02387 SepRemoveDisabledGroupsAndPrivileges( 02388 NewToken, 02389 Flags, 02390 GroupCount, 02391 GroupsToDisable, 02392 PrivilegeCount, 02393 PrivilegesToDelete 02394 ); 02395 02396 02397 02398 #ifdef TOKEN_DEBUG 02399 02400 // 02401 // Debug 02402 DbgPrint("\n"); 02403 DbgPrint("\n"); 02404 DbgPrint("\n"); 02405 DbgPrint("Filter token:\n"); 02406 SepDumpToken( NewToken ); 02407 // Debug 02408 // 02410 #endif //TOKEN_DEBUG 02411 02412 // 02413 // Release the source token. 02414 // 02415 02416 SepReleaseTokenReadLock( ExistingToken ); 02417 02418 02419 (*FilteredToken) = NewToken; 02420 return Status; 02421 }

VOID SepFreeDefaultDacl IN PTOKEN  Token  ) 
 

Definition at line 635 of file tokenset.c.

References NULL, PAGED_CODE, SeLengthSid, and Token.

Referenced by NtSetInformationToken().

00642 : 00643 00644 Free up the space in the dynamic part of the token take up by the default 00645 discretionary access control list. 00646 00647 The token is assumed to be locked for write access before calling 00648 this routine. 00649 00650 Arguments: 00651 00652 Token - Pointer to the token. 00653 00654 Return Value: 00655 00656 None. 00657 00658 --*/ 00659 { 00660 ULONG PrimaryGroupSize; 00661 00662 PAGED_CODE(); 00663 00664 // 00665 // Add the size of the Default Dacl (if there is one) to the 00666 // DynamicAvailable field. 00667 // 00668 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00669 00670 Token->DynamicAvailable += Token->DefaultDacl->AclSize; 00671 Token->DefaultDacl = NULL; 00672 00673 } 00674 00675 // 00676 // If it is not already at the beginning of the dynamic part, move 00677 // the primary group there (remember to update the pointer to it). 00678 // 00679 00680 if (Token->DynamicPart != (PULONG)(Token->PrimaryGroup)) { 00681 00682 PrimaryGroupSize = SeLengthSid( Token->PrimaryGroup ); 00683 00684 RtlMoveMemory( 00685 (PVOID)(Token->DynamicPart), 00686 (PVOID)(Token->PrimaryGroup), 00687 PrimaryGroupSize 00688 ); 00689 00690 Token->PrimaryGroup = (PSID)(Token->DynamicPart); 00691 } 00692 00693 return; 00694 }

VOID SepFreePrimaryGroup IN PTOKEN  Token  ) 
 

Definition at line 576 of file tokenset.c.

References PAGED_CODE, SeLengthSid, and Token.

Referenced by NtSetInformationToken().

00583 : 00584 00585 Free up the space in the dynamic part of the token take up by the primary 00586 group. 00587 00588 The token is assumed to be locked for write access before calling 00589 this routine. 00590 00591 Arguments: 00592 00593 Token - Pointer to the token. 00594 00595 Return Value: 00596 00597 None. 00598 00599 --*/ 00600 { 00601 PAGED_CODE(); 00602 00603 // 00604 // Add the size of the primary group to the DynamicAvailable field. 00605 // 00606 00607 Token->DynamicAvailable += SeLengthSid( Token->PrimaryGroup ); 00608 00609 // 00610 // If there is a default discretionary ACL, and it is not already at the 00611 // beginning of the dynamic part, move it there (remember to update the 00612 // pointer to it). 00613 // 00614 00615 if (ARGUMENT_PRESENT(Token->DefaultDacl)) { 00616 if (Token->DynamicPart != (PULONG)(Token->DefaultDacl)) { 00617 00618 RtlMoveMemory( 00619 (PVOID)(Token->DynamicPart), 00620 (PVOID)(Token->DefaultDacl), 00621 Token->DefaultDacl->AclSize 00622 ); 00623 00624 Token->DefaultDacl = (PACL)(Token->DynamicPart); 00625 00626 } 00627 } 00628 00629 return; 00630 00631 }

BOOLEAN SepIdAssignableAsOwner IN PTOKEN  Token,
IN ULONG  Index
 

Definition at line 2813 of file token.c.

References Index, PAGED_CODE, SepTokenGroupAttributes, Token, and TRUE.

Referenced by NtSetInformationToken(), and SepValidOwnerSubjectContext().

02821 : 02822 02823 This routine returns a boolean value indicating whether the user 02824 or group ID in the specified token with the specified index is 02825 assignable as the owner of an object. 02826 02827 If the index is 0, which is always the USER ID, then the ID is 02828 assignable as owner. Otherwise, the ID is that of a group, and 02829 it must have the "Owner" attribute set to be assignable. 02830 02831 02832 02833 Arguments: 02834 02835 Token - Pointer to a locked Token to use. 02836 02837 Index - Index into the Token's UserAndGroupsArray. This value 02838 is assumed to be valid. 02839 02840 Return Value: 02841 02842 TRUE - Indicates the index corresponds to an ID that may be assigned 02843 as the owner of objects. 02844 02845 FALSE - Indicates the index does not correspond to an ID that may be 02846 assigned as the owner of objects. 02847 02848 --*/ 02849 { 02850 PAGED_CODE(); 02851 02852 if (Index == 0) { 02853 02854 return TRUE; 02855 02856 } else { 02857 02858 return (BOOLEAN) 02859 ( (SepTokenGroupAttributes(Token,Index) & SE_GROUP_OWNER) 02860 != 0 02861 ); 02862 } 02863 }

VOID SepMakeTokenEffectiveOnly IN PTOKEN  Token  ) 
 

Definition at line 806 of file tokendup.c.

References ASSERT, Index, PAGED_CODE, RtlEqualSid(), SeAliasAdminsSid, SepTokenGroupAttributes, SepTokenPrivilegeAttributes, Token, and TOKEN_HAS_ADMIN_GROUP.

Referenced by SepDuplicateToken().

00814 : 00815 00816 This routine eliminates all but the effective groups and privileges from 00817 a token. It does this by moving elements of the SID and privileges arrays 00818 to overwrite lapsed IDs/privileges, and then reducing the array element 00819 counts. This results in wasted memory within the token object. 00820 00821 One side effect of this routine is that a token that initially had a 00822 default owner ID corresponding to a lapsed group will be changed so 00823 that the default owner ID is the user ID. 00824 00825 THIS ROUTINE MUST BE CALLED ONLY AS PART OF TOKEN CREATION (FOR TOKENS 00826 WHICH HAVE NOT YET BEEN INSERTED INTO AN OBJECT TABLE.) THIS ROUTINE 00827 MODIFIES READ ONLY TOKEN FIELDS. 00828 00829 Note that since we are operating on a token that is not yet visible 00830 to the user, we do not bother acquiring a read lock on the token 00831 being modified. 00832 00833 Arguments: 00834 00835 Token - Points to the token to be made effective only. 00836 00837 Return Value: 00838 00839 None. 00840 00841 --*/ 00842 { 00843 00844 ULONG Index; 00845 ULONG ElementCount; 00846 00847 PAGED_CODE(); 00848 00849 // 00850 // Walk the privilege array, discarding any lapsed privileges 00851 // 00852 00853 ElementCount = Token->PrivilegeCount; 00854 Index = 0; 00855 00856 while (Index < ElementCount) { 00857 00858 // 00859 // If this privilege is not enabled, replace it with the one at 00860 // the end of the array and reduce the size of the array by one. 00861 // Otherwise, move on to the next entry in the array. 00862 // 00863 00864 if ( !(SepTokenPrivilegeAttributes(Token,Index) & SE_PRIVILEGE_ENABLED) 00865 ) { 00866 00867 (Token->Privileges)[Index] = 00868 (Token->Privileges)[ElementCount - 1]; 00869 ElementCount -= 1; 00870 00871 } else { 00872 00873 Index += 1; 00874 00875 } 00876 00877 } // endwhile 00878 00879 Token->PrivilegeCount = ElementCount; 00880 00881 // 00882 // Walk the UserAndGroups array (except for the first entry, which is 00883 // the user - and can't be disabled) discarding any lapsed groups. 00884 // 00885 00886 ElementCount = Token->UserAndGroupCount; 00887 ASSERT( ElementCount >= 1 ); // Must be at least a user ID 00888 Index = 1; // Start at the first group, not the user ID. 00889 00890 while (Index < ElementCount) { 00891 00892 // 00893 // If this group is not enabled, replace it with the one at 00894 // the end of the array and reduce the size of the array by one. 00895 // 00896 00897 if ( !(SepTokenGroupAttributes(Token, Index) & SE_GROUP_ENABLED) && 00898 !(SepTokenGroupAttributes(Token, Index) & SE_GROUP_USE_FOR_DENY_ONLY) ) { 00899 00900 // 00901 // Reset the TOKEN_HAS_ADMIN_GROUP flag 00902 // 00903 00904 if (RtlEqualSid( 00905 Token->UserAndGroups[Index].Sid, 00906 SeAliasAdminsSid 00907 )) { 00908 Token->TokenFlags &= ~TOKEN_HAS_ADMIN_GROUP; 00909 } 00910 00911 00912 (Token->UserAndGroups)[Index] = 00913 (Token->UserAndGroups)[ElementCount - 1]; 00914 ElementCount -= 1; 00915 00916 00917 00918 } else { 00919 00920 Index += 1; 00921 00922 } 00923 00924 } // endwhile 00925 00926 Token->UserAndGroupCount = ElementCount; 00927 00928 return; 00929 }

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 }

BOOLEAN SepPrivilegeCheck IN PTOKEN  Token,
IN OUT PLUID_AND_ATTRIBUTES  RequiredPrivileges,
IN ULONG  RequiredPrivilegeCount,
IN ULONG  PrivilegeSetControl,
IN KPROCESSOR_MODE  PreviousMode
 

Definition at line 38 of file privileg.c.

References FALSE, KernelMode, PAGED_CODE, RtlEqualLuid(), SepAcquireTokenReadLock, SepReleaseTokenReadLock, Token, and TRUE.

Referenced by NtPrivilegeCheck(), SeCheckAuditPrivilege(), SePrivilegeCheck(), and SepSinglePrivilegeCheck().

00047 : 00048 00049 Worker routine for SePrivilegeCheck 00050 00051 Arguments: 00052 00053 Token - The user's effective token. 00054 00055 RequiredPrivileges - A privilege set describing the required 00056 privileges. The UsedForAccess bits will be set in any privilege 00057 that is actually used (usually all of them). 00058 00059 RequiredPrivilegeCount - How many privileges are in the 00060 RequiredPrivileges set. 00061 00062 PrivilegeSetControl - Describes how many privileges are required. 00063 00064 PreviousMode - The previous processor mode. 00065 00066 Return Value: 00067 00068 Returns TRUE if requested privileges are granted, FALSE otherwise. 00069 00070 --*/ 00071 00072 { 00073 PLUID_AND_ATTRIBUTES CurrentRequiredPrivilege; 00074 PLUID_AND_ATTRIBUTES CurrentTokenPrivilege; 00075 00076 BOOLEAN RequiredAll; 00077 00078 ULONG TokenPrivilegeCount; 00079 ULONG MatchCount = 0; 00080 00081 ULONG i; 00082 ULONG j; 00083 00084 PAGED_CODE(); 00085 00086 // 00087 // Take care of kernel callers first 00088 // 00089 00090 if (PreviousMode == KernelMode) { 00091 00092 return(TRUE); 00093 00094 } 00095 00096 SepAcquireTokenReadLock( Token ); 00097 00098 TokenPrivilegeCount = Token->PrivilegeCount; 00099 00100 // 00101 // Save whether we require ALL of them or ANY 00102 // 00103 00104 RequiredAll = (BOOLEAN)(PrivilegeSetControl & PRIVILEGE_SET_ALL_NECESSARY); 00105 00106 for ( i = 0 , CurrentRequiredPrivilege = RequiredPrivileges ; 00107 i < RequiredPrivilegeCount ; 00108 i++, CurrentRequiredPrivilege++ ) { 00109 00110 for ( j = 0, CurrentTokenPrivilege = Token->Privileges; 00111 j < TokenPrivilegeCount ; 00112 j++, CurrentTokenPrivilege++ ) { 00113 00114 if ((CurrentTokenPrivilege->Attributes & SE_PRIVILEGE_ENABLED) && 00115 (RtlEqualLuid(&CurrentTokenPrivilege->Luid, 00116 &CurrentRequiredPrivilege->Luid)) 00117 ) { 00118 00119 CurrentRequiredPrivilege->Attributes |= 00120 SE_PRIVILEGE_USED_FOR_ACCESS; 00121 MatchCount++; 00122 break; // start looking for next one 00123 } 00124 00125 } 00126 00127 } 00128 00129 SepReleaseTokenReadLock( Token ); 00130 00131 // 00132 // If we wanted ANY and didn't get any, return failure. 00133 // 00134 00135 if (!RequiredAll && (MatchCount == 0)) { 00136 00137 return (FALSE); 00138 00139 } 00140 00141 // 00142 // If we wanted ALL and didn't get all, return failure. 00143 // 00144 00145 if (RequiredAll && (MatchCount != RequiredPrivilegeCount)) { 00146 00147 return(FALSE); 00148 } 00149 00150 return(TRUE); 00151 00152 }

VOID SepRemoveDisabledGroupsAndPrivileges IN PTOKEN  Token,
IN ULONG  Flags,
IN ULONG  GroupCount,
IN PSID_AND_ATTRIBUTES  GroupsToDisable,
IN ULONG  PrivilegeCount,
IN PLUID_AND_ATTRIBUTES  PrivilegesToDelete
 

Definition at line 1041 of file tokendup.c.

References ASSERT, FALSE, Index, NULL, PAGED_CODE, RtlEqualLuid(), RtlEqualSid(), SeAliasAdminsSid, SeChangeNotifyPrivilege, SepSidInSidAndAttributes(), Token, TOKEN_HAS_ADMIN_GROUP, TOKEN_HAS_TRAVERSE_PRIVILEGE, and TRUE.

Referenced by SepFilterToken().

01052 : 01053 01054 This routine eliminates all groups and privileges that are marked 01055 to be deleted/disabled. It does this by looping through the groups in 01056 the token and checking each one agains the groups to disable. Similary 01057 the privilegs are compared. It does this by moving elements of the SID and privileges arrays 01058 to overwrite lapsed IDs/privileges, and then reducing the array element 01059 counts. This results in wasted memory within the token object. 01060 01061 01062 THIS ROUTINE MUST BE CALLED ONLY AS PART OF TOKEN CREATION (FOR TOKENS 01063 WHICH HAVE NOT YET BEEN INSERTED INTO AN OBJECT TABLE.) THIS ROUTINE 01064 MODIFIES READ ONLY TOKEN FIELDS. 01065 01066 Note that since we are operating on a token that is not yet visible 01067 to the user, we do not bother acquiring a read lock on the token 01068 being modified. 01069 01070 Arguments: 01071 01072 Token - Points to the token to be made effective only. 01073 01074 Flags - Flags indicating additional filtering. The flags may be: 01075 01076 DISABLE_ALL_GROUPS - disable all groups in token 01077 DELETE_ALL_PRIVILEGES - Disable all privileges 01078 01079 GroupCount - Count of groups to be removed 01080 01081 GroupsToDisable - Groups to disable and mark with SE_GROUP_USE_FOR_DENY_ONLY 01082 01083 PrivilegeCount - Count of privileges to remove 01084 01085 PrivilegesToDelete - List of privileges to remove 01086 01087 Return Value: 01088 01089 None. 01090 01091 --*/ 01092 { 01093 01094 ULONG Index; 01095 ULONG Index2; 01096 ULONG ElementCount; 01097 BOOLEAN Found; 01098 01099 PAGED_CODE(); 01100 01101 // 01102 // Walk the privilege array, discarding any lapsed privileges 01103 // 01104 01105 ElementCount = Token->PrivilegeCount; 01106 Index = 0; 01107 01108 while (Index < ElementCount) { 01109 01110 // 01111 // If the caller asked us to disable all privileges except change 01112 // notify, do so now. 01113 // 01114 01115 if (((Flags & DISABLE_MAX_PRIVILEGE) != 0) && 01116 !RtlEqualLuid( 01117 &Token->Privileges[Index].Luid, 01118 &SeChangeNotifyPrivilege 01119 )) { 01120 01121 (Token->Privileges)[Index] = 01122 (Token->Privileges)[ElementCount - 1]; 01123 ElementCount -= 1; 01124 01125 } else { 01126 01127 // 01128 // If this privilege is in the list of those to be removed, replace it 01129 // with the one at the end of the array and reduce the size of the 01130 // array by one. Otherwise, move on to the next entry in the array. 01131 // 01132 01133 Found = FALSE; 01134 for (Index2 = 0; Index2 < PrivilegeCount ; Index2++ ) { 01135 if (RtlEqualLuid( 01136 &Token->Privileges[Index].Luid, 01137 &PrivilegesToDelete[Index2].Luid 01138 )) { 01139 (Token->Privileges)[Index] = 01140 (Token->Privileges)[ElementCount - 1]; 01141 ElementCount -= 1; 01142 01143 // 01144 // If this was SeChangeNotifyPrivilege, we need to turn off 01145 // the TOKEN_HAS_TRAVERSE_PRIVILEGE in the token 01146 // 01147 01148 if (RtlEqualLuid( 01149 &PrivilegesToDelete[Index2].Luid, 01150 &SeChangeNotifyPrivilege 01151 )) { 01152 Token->TokenFlags &= ~TOKEN_HAS_TRAVERSE_PRIVILEGE; 01153 } 01154 01155 01156 Found = TRUE; 01157 break; 01158 01159 } 01160 } 01161 01162 if (!Found) { 01163 Index += 1; 01164 } 01165 } 01166 } // endwhile 01167 01168 Token->PrivilegeCount = ElementCount; 01169 01170 // 01171 // Walk the UserAndGroups array marking any disabled groups. 01172 // 01173 01174 ElementCount = Token->UserAndGroupCount; 01175 ASSERT( ElementCount >= 1 ); // Must be at least a user ID 01176 Index = 0; // Start at the first group, not the user ID. 01177 01178 while (Index < ElementCount) { 01179 01180 // 01181 // If this group is not enabled, replace it with the one at 01182 // the end of the array and reduce the size of the array by one. 01183 // 01184 01185 if ( SepSidInSidAndAttributes( 01186 GroupsToDisable, 01187 GroupCount, 01188 NULL, // no principal self sid 01189 Token->UserAndGroups[Index].Sid 01190 )){ 01191 01192 (Token->UserAndGroups)[Index].Attributes &= ~(SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT); 01193 (Token->UserAndGroups)[Index].Attributes |= SE_GROUP_USE_FOR_DENY_ONLY; 01194 01195 // 01196 // If this was the owner, reset the owner to be the user 01197 // 01198 01199 if (Index == Token->DefaultOwnerIndex) { 01200 Token->DefaultOwnerIndex = 0; 01201 } 01202 01203 // 01204 // If this is the admins sid, turn off the admin group flag 01205 // 01206 01207 if (RtlEqualSid( 01208 Token->UserAndGroups[Index].Sid, 01209 SeAliasAdminsSid 01210 )) { 01211 01212 Token->TokenFlags &= ~TOKEN_HAS_ADMIN_GROUP; 01213 } 01214 } 01215 01216 Index += 1; 01217 01218 01219 } // endwhile 01220 01221 01222 return; 01223 }

BOOLEAN SepSidInSidAndAttributes IN PSID_AND_ATTRIBUTES  SidAndAttributes,
IN ULONG  SidCount,
IN PSID  PrincipalSelfSid,
IN PSID  Sid
 

Definition at line 933 of file tokendup.c.

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

Referenced by SepFilterToken(), and SepRemoveDisabledGroupsAndPrivileges().

00942 : 00943 00944 Checks to see if a given SID is in the given token. 00945 00946 N.B. The code to compute the length of a SID and test for equality 00947 is duplicated from the security runtime since this is such a 00948 frequently used routine. 00949 00950 Arguments: 00951 00952 SidAndAttributes - Pointer to the sid and attributes to be examined 00953 00954 PrincipalSelfSid - If the object being access checked is an object which 00955 represents a principal (e.g., a user object), this parameter should 00956 be the SID of the object. Any ACE containing the constant 00957 PRINCIPAL_SELF_SID is replaced by this SID. 00958 00959 The parameter should be NULL if the object does not represent a principal. 00960 00961 00962 Sid - Pointer to the SID of interest 00963 00964 Return Value: 00965 00966 A value of TRUE indicates that the SID is in the token, FALSE 00967 otherwise. 00968 00969 --*/ 00970 00971 { 00972 00973 ULONG i; 00974 PISID MatchSid; 00975 ULONG SidLength; 00976 PTOKEN Token; 00977 PSID_AND_ATTRIBUTES TokenSid; 00978 ULONG UserAndGroupCount; 00979 00980 PAGED_CODE(); 00981 00982 00983 if (!ARGUMENT_PRESENT( SidAndAttributes ) ) { 00984 return(FALSE); 00985 } 00986 00987 // 00988 // If Sid is the constant PrincipalSelfSid, 00989 // replace it with the passed in PrincipalSelfSid. 00990 // 00991 00992 if ( PrincipalSelfSid != NULL && 00993 RtlEqualSid( SePrincipalSelfSid, Sid ) ) { 00994 Sid = PrincipalSelfSid; 00995 } 00996 00997 // 00998 // Get the length of the source SID since this only needs to be computed 00999 // once. 01000 // 01001 01002 SidLength = 8 + (4 * ((PISID)Sid)->SubAuthorityCount); 01003 01004 // 01005 // Get address of user/group array and number of user/groups. 01006 // 01007 01008 TokenSid = SidAndAttributes; 01009 UserAndGroupCount = SidCount; 01010 01011 // 01012 // Scan through the user/groups and attempt to find a match with the 01013 // specified SID. 01014 // 01015 01016 for (i = 0 ; i < UserAndGroupCount ; i += 1) { 01017 MatchSid = (PISID)TokenSid->Sid; 01018 01019 // 01020 // If the SID revision and length matches, then compare the SIDs 01021 // for equality. 01022 // 01023 01024 if ((((PISID)Sid)->Revision == MatchSid->Revision) && 01025 (SidLength == (8 + (4 * (ULONG)MatchSid->SubAuthorityCount)))) { 01026 if (RtlEqualMemory(Sid, MatchSid, SidLength)) { 01027 01028 return TRUE; 01029 01030 } 01031 } 01032 01033 TokenSid += 1; 01034 } 01035 01036 return FALSE; 01037 }

VOID SepTokenDeleteMethod IN PVOID  Token  ) 
 

Definition at line 2156 of file token.c.

References ExFreePool(), PAGED_CODE, SepDeReferenceLogonSession(), SepFreeProxyData(), and Token.

Referenced by SepTokenInitialization().

02162 : 02163 02164 This function is the token object type-specific delete method. 02165 It is needed to ensure that all memory allocated for the token 02166 gets deallocated. 02167 02168 Arguments: 02169 02170 Token - Points to the token object being deleted. 02171 02172 Return Value: 02173 02174 None. 02175 02176 --*/ 02177 02178 { 02179 PAGED_CODE(); 02180 02181 // 02182 // De-reference the logon session referenced by this token object 02183 // 02184 02185 SepDeReferenceLogonSession( &(((TOKEN *)Token)->AuthenticationId) ); 02186 02187 02188 // 02189 // If the token has an associated Dynamic part, deallocate it. 02190 // 02191 02192 if (ARGUMENT_PRESENT( ((TOKEN *)Token)->DynamicPart)) { 02193 ExFreePool( ((TOKEN *)Token)->DynamicPart ); 02194 } 02195 02196 // 02197 // Free the Proxy and Global audit structures if present. 02198 // 02199 02200 if (ARGUMENT_PRESENT(((TOKEN *) Token)->ProxyData)) { 02201 SepFreeProxyData( ((TOKEN *)Token)->ProxyData ); 02202 } 02203 02204 if (ARGUMENT_PRESENT(((TOKEN *)Token)->AuditData )) { 02205 ExFreePool( (((TOKEN *)Token)->AuditData) ); 02206 } 02207 02208 02209 return; 02210 }

BOOLEAN SepTokenInitialization VOID   ) 
 

Definition at line 1460 of file token.c.

References ExInitializeResource, L, NT_SUCCESS, NTSTATUS(), NULL, ObCreateObjectType(), PAGED_CODE, PagedPool, RtlInitUnicodeString(), SepTokenDeleteMethod(), SepTokenLock, SepTokenMapping, SepTokenObjectType, Status, and TRUE.

Referenced by SepInitializationPhase0().

01464 : 01465 01466 This function creates the token object type descriptor at system 01467 initialization and stores the address of the object type descriptor 01468 in global storage. It also created token related global variables. 01469 01470 Furthermore, some number of pseudo tokens are created during system 01471 initialization. These tokens are tracked down and replaced with 01472 real tokens. 01473 01474 Arguments: 01475 01476 None. 01477 01478 Return Value: 01479 01480 A value of TRUE is returned if the object type descriptor is 01481 successfully initialized. Otherwise a value of FALSE is returned. 01482 01483 --*/ 01484 01485 { 01486 01487 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 01488 NTSTATUS Status; 01489 UNICODE_STRING TypeName; 01490 01491 PAGED_CODE(); 01492 01493 // 01494 // Initialize string descriptor. 01495 // 01496 01497 RtlInitUnicodeString(&TypeName, L"Token"); 01498 01499 01500 // 01501 // Create the global token lock 01502 // 01503 01504 ExInitializeResource(&SepTokenLock); 01505 01506 01507 #if 0 01508 BUG, BUG Need to get system default ACL to protect token object 01509 #endif 01510 01511 // 01512 // Create object type descriptor. 01513 // 01514 01515 RtlZeroMemory(&ObjectTypeInitializer,sizeof(ObjectTypeInitializer)); 01516 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 01517 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 01518 ObjectTypeInitializer.GenericMapping = SepTokenMapping; 01519 ObjectTypeInitializer.SecurityRequired = TRUE; 01520 ObjectTypeInitializer.UseDefaultObject = TRUE; 01521 ObjectTypeInitializer.PoolType = PagedPool; 01522 ObjectTypeInitializer.ValidAccessMask = TOKEN_ALL_ACCESS; 01523 ObjectTypeInitializer.DeleteProcedure = SepTokenDeleteMethod; 01524 01525 Status = ObCreateObjectType(&TypeName, 01526 &ObjectTypeInitializer, 01527 (PSECURITY_DESCRIPTOR)NULL, // BUG, BUG assign real protection 01528 &SepTokenObjectType 01529 ); 01530 01531 01532 #if 0 01533 BUG, BUG Now track down all pseudo tokens used during system initialization 01534 BUG, BUG and replace them with real ones. 01535 #endif 01536 01537 // 01538 // If the object type descriptor was successfully created, then 01539 // return a value of TRUE. Otherwise return a value of FALSE. 01540 // 01541 01542 return (BOOLEAN)NT_SUCCESS(Status); 01543 }


Variable Documentation

ERESOURCE SepTokenLock
 

Definition at line 674 of file tokenp.h.

Referenced by SepTokenInitialization().

GENERIC_MAPPING SepTokenMapping
 

Definition at line 671 of file tokenp.h.

Referenced by SepTokenInitialization().

POBJECT_TYPE SepTokenObjectType
 

Definition at line 672 of file tokenp.h.


Generated on Sat May 15 19:45:48 2004 for test by doxygen 1.3.7