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

tokendup.c File Reference

#include "sep.h"
#include "tokenp.h"

Go to the source code of this file.

Defines

#define MAX(_x_, _y_)   ((_x_) > (_y_) ? (_x_) : (_y_))

Functions

NTSTATUS NtDuplicateToken (IN HANDLE ExistingTokenHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN BOOLEAN EffectiveOnly, IN TOKEN_TYPE TokenType, OUT PHANDLE NewTokenHandle)
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)
VOID SepMakeTokenEffectiveOnly (IN PTOKEN Token)
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)
NTSTATUS SeCopyClientToken (IN PACCESS_TOKEN ClientToken, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, IN KPROCESSOR_MODE RequestorMode, OUT PACCESS_TOKEN *DuplicateToken)
NTSTATUS NtFilterToken (IN HANDLE ExistingTokenHandle, IN ULONG Flags, IN PTOKEN_GROUPS SidsToDisable OPTIONAL, IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, IN PTOKEN_GROUPS RestrictedSids OPTIONAL, OUT PHANDLE NewTokenHandle)
NTSTATUS SeFilterToken (IN PACCESS_TOKEN ExistingToken, IN ULONG Flags, IN PTOKEN_GROUPS SidsToDisable OPTIONAL, IN PTOKEN_PRIVILEGES PrivilegesToDelete OPTIONAL, IN PTOKEN_GROUPS RestrictedSids OPTIONAL, OUT PACCESS_TOKEN *NewToken)
NTSTATUS SeFastFilterToken (IN PACCESS_TOKEN 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 PACCESS_TOKEN *FilteredToken)
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)


Define Documentation

#define MAX _x_,
_y_   )     ((_x_) > (_y_) ? (_x_) : (_y_))
 

Referenced by SepFilterToken(), and xxxDrawCaptionBar().


Function Documentation

NTSTATUS NtDuplicateToken IN HANDLE  ExistingTokenHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
IN BOOLEAN  EffectiveOnly,
IN TOKEN_TYPE  TokenType,
OUT PHANDLE  NewTokenHandle
 

Definition at line 46 of file tokendup.c.

References ASSERT, DbgPrint, EXCEPTION_EXECUTE_HANDLER, FALSE, _OBJECT_HANDLE_INFORMATION::GrantedAccess, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObInsertObject(), ObjectAttributes, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForWriteHandle, PTOKEN, SeCaptureSecurityQos(), SecurityQos, SeFreeCapturedSecurityQos(), SepAcquireTokenReadLock, SepDuplicateToken(), SepReleaseTokenReadLock, SepTokenObjectType, Status, and Token.

Referenced by main(), RtlImpersonateSelf(), TestTokenDuplicate(), and TestTokenImpersonation().

00058 : 00059 00060 Create a new token that is a duplicate of an existing token. 00061 00062 Arguments: 00063 00064 ExistingTokenHandle - Is a handle to a token already open for 00065 TOKEN_DUPLICATE access. 00066 00067 DesiredAccess - Is an access mask indicating which access types 00068 are desired to the newly created token. If specified as zero, 00069 the granted access mask of the existing token handle 00070 is used as the desired access mask for the new token. 00071 00072 ObjectAttributes - Points to the standard object attributes data 00073 structure. Refer to the NT Object Management 00074 Specification for a description of this data structure. 00075 00076 If the new token type is TokenImpersonation, then this 00077 parameter may be used to specify the impersonation level 00078 of the new token. If no value is provided, and the source 00079 token is an impersonation token, then the impersonation level 00080 of the source will become that of the target as well. If the 00081 source token is a primary token, then an impersonation level 00082 must be explicitly provided. 00083 00084 If the token being duplicated is an impersonation token, and 00085 an impersonation level is explicitly provided for the target, 00086 then the value provided must not be greater than that of the 00087 source token. For example, an Identification level token can 00088 not be duplicated to produce a Delegation level token. 00089 00090 EffectiveOnly - Is a boolean flag indicating whether the entire 00091 source token should be duplicated into the target token or 00092 just the effective (currently enabled) part of the token. 00093 This provides a means for a caller of a protected subsystem 00094 to limit which privileges and optional groups are made 00095 available to the protected subsystem. A value of TRUE 00096 indicates only the currently enabled parts of the source 00097 token are to be duplicated. Otherwise, the entire source 00098 token is duplicated. 00099 00100 TokenType - Indicates which type of object the new object is to 00101 be created as (primary or impersonation). If you are duplicating 00102 an Impersonation token to produce a Primary token, then 00103 the Impersonation token must have an impersonation level of 00104 either DELEGATE or IMPERSONATE. 00105 00106 00107 NewTokenHandle - Receives the handle of the newly created token. 00108 00109 Return Value: 00110 00111 STATUS_SUCCESS - Indicates the operation was successful. 00112 00113 STATUS_INVALID_PARAMETER - Indicates one or more of the parameter values 00114 was invalid. This value is returned if the target token is not 00115 an impersonation token. 00116 00117 STATUS_BAD_IMPERSONATION_LEVEL - Indicates the impersonation level 00118 requested for the duplicate token is not compatible with the 00119 level of the source token. The duplicate token may not be assigned 00120 a level greater than that of the source token. 00121 00122 --*/ 00123 { 00124 00125 PTOKEN Token; 00126 PTOKEN NewToken; 00127 KPROCESSOR_MODE PreviousMode; 00128 NTSTATUS Status; 00129 00130 SECURITY_ADVANCED_QUALITY_OF_SERVICE SecurityQos; 00131 BOOLEAN SecurityQosPresent = FALSE; 00132 HANDLE LocalHandle; 00133 00134 OBJECT_HANDLE_INFORMATION HandleInformation; 00135 ACCESS_MASK EffectiveDesiredAccess; 00136 00137 PAGED_CODE(); 00138 00139 PreviousMode = KeGetPreviousMode(); 00140 00141 // 00142 // Probe parameters 00143 // 00144 00145 if (PreviousMode != KernelMode) { 00146 00147 try { 00148 00149 // 00150 // Make sure the TokenType is valid 00151 // 00152 00153 if ( (TokenType < TokenPrimary) || (TokenType > TokenImpersonation) ) { 00154 return(STATUS_INVALID_PARAMETER); 00155 } 00156 00157 // 00158 // Make sure we can write the handle 00159 // 00160 00161 ProbeForWriteHandle(NewTokenHandle); 00162 00163 00164 } except(EXCEPTION_EXECUTE_HANDLER) { 00165 return GetExceptionCode(); 00166 } // end_try 00167 00168 } //end_if 00169 00170 00171 00172 Status = SeCaptureSecurityQos( 00173 ObjectAttributes, 00174 PreviousMode, 00175 &SecurityQosPresent, 00176 &SecurityQos 00177 ); 00178 00179 if (!NT_SUCCESS(Status)) { 00180 return Status; 00181 } 00182 00183 00184 // 00185 // Check the handle's access to the existing token and get 00186 // a pointer to that token. Pick up the default desired 00187 // access mask from the handle while we're at it. 00188 // 00189 00190 Status = ObReferenceObjectByHandle( 00191 ExistingTokenHandle, // Handle 00192 TOKEN_DUPLICATE, // DesiredAccess 00193 SepTokenObjectType, // ObjectType 00194 PreviousMode, // AccessMode 00195 (PVOID *)&Token, // Object 00196 &HandleInformation // GrantedAccess 00197 ); 00198 00199 if ( !NT_SUCCESS(Status) ) { 00200 00201 if (SecurityQosPresent) { 00202 SeFreeCapturedSecurityQos( &SecurityQos ); 00203 } 00204 return Status; 00205 } 00206 00207 00208 #ifdef TOKEN_DEBUG 00209 00210 // 00211 // Debug 00212 SepAcquireTokenReadLock( Token ); 00213 DbgPrint("\n"); 00214 DbgPrint("\n"); 00215 DbgPrint("Token being duplicated: \n"); 00216 SepDumpToken( Token ); 00217 SepReleaseTokenReadLock( Token ); 00218 // Debug 00219 // 00221 #endif //TOKEN_DEBUG 00222 00223 00224 // 00225 // Check to see if an alternate desired access mask was provided. 00226 // 00227 00228 if (ARGUMENT_PRESENT((PVOID)(ULONG_PTR)DesiredAccess)) { 00229 00230 EffectiveDesiredAccess = DesiredAccess; 00231 00232 } else { 00233 00234 EffectiveDesiredAccess = HandleInformation.GrantedAccess; 00235 } 00236 00237 00238 // 00239 // If no impersonation level was specified, pick one up from 00240 // the source token. 00241 // 00242 00243 if ( !SecurityQosPresent ) { 00244 00245 SecurityQos.ImpersonationLevel = Token->ImpersonationLevel; 00246 00247 } 00248 00249 00250 00251 if (Token->TokenType == TokenImpersonation) { 00252 00253 // 00254 // Make sure a legitimate transformation is being requested: 00255 // 00256 // (1) The impersonation level of a target duplicate must not 00257 // exceed that of the source token. 00258 // 00259 // 00260 00261 ASSERT( SecurityDelegation > SecurityImpersonation ); 00262 ASSERT( SecurityImpersonation > SecurityIdentification ); 00263 ASSERT( SecurityIdentification > SecurityAnonymous ); 00264 00265 if ( (SecurityQos.ImpersonationLevel > Token->ImpersonationLevel) ) { 00266 00267 ObDereferenceObject( (PVOID)Token ); 00268 if (SecurityQosPresent) { 00269 SeFreeCapturedSecurityQos( &SecurityQos ); 00270 } 00271 return STATUS_BAD_IMPERSONATION_LEVEL; 00272 } 00273 00274 } 00275 00276 // 00277 // If we are producing a Primary token from an impersonation 00278 // token, then specify an impersonation level of at least 00279 // Impersonate. 00280 // 00281 00282 if ( (Token->TokenType == TokenImpersonation) && 00283 (TokenType == TokenPrimary) && 00284 (Token->ImpersonationLevel < SecurityImpersonation) 00285 ) { 00286 ObDereferenceObject( (PVOID)Token ); 00287 if (SecurityQosPresent) { 00288 SeFreeCapturedSecurityQos( &SecurityQos ); 00289 } 00290 return STATUS_BAD_IMPERSONATION_LEVEL; 00291 } 00292 00293 // 00294 // Duplicate the existing token 00295 // 00296 00297 NewToken = NULL; 00298 Status = SepDuplicateToken( 00299 Token, 00300 ObjectAttributes, 00301 EffectiveOnly, 00302 TokenType, 00303 SecurityQos.ImpersonationLevel, 00304 PreviousMode, 00305 &NewToken 00306 ); 00307 00308 00309 if (NT_SUCCESS(Status)) { 00310 00311 // 00312 // Insert the new token 00313 // 00314 00315 Status = ObInsertObject( NewToken, 00316 NULL, 00317 EffectiveDesiredAccess, 00318 0, 00319 (PVOID *)NULL, 00320 &LocalHandle 00321 ); 00322 00323 if (!NT_SUCCESS( Status )) { 00324 #ifdef TOKEN_DEBUG 00325 DbgPrint( "SE: ObInsertObject failed (%x) for token at %x\n", Status, NewToken ); 00326 #endif 00327 } 00328 00329 } else 00330 if (NewToken != NULL) { 00331 #ifdef TOKEN_DEBUG 00332 DbgPrint( "SE: SepDuplicateToken failed (%x) but allocated token at %x\n", Status, NewToken ); 00333 #endif 00334 } 00335 00336 // 00337 // We no longer need our reference to the source token 00338 // 00339 00340 ObDereferenceObject( (PVOID)Token ); 00341 00342 if (SecurityQosPresent) { 00343 SeFreeCapturedSecurityQos( &SecurityQos ); 00344 } 00345 00346 // BUGWARNING Probably need to audit here 00347 00348 // 00349 // Return the new handle 00350 // 00351 00352 if (NT_SUCCESS(Status)) { 00353 try { *NewTokenHandle = LocalHandle; } 00354 except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } 00355 } 00356 00357 return Status; 00358 }

NTSTATUS NtFilterToken IN HANDLE  ExistingTokenHandle,
IN ULONG  Flags,
IN PTOKEN_GROUPS SidsToDisable  OPTIONAL,
IN PTOKEN_PRIVILEGES PrivilegesToDelete  OPTIONAL,
IN PTOKEN_GROUPS RestrictedSids  OPTIONAL,
OUT PHANDLE  NewTokenHandle
 

Definition at line 1306 of file tokendup.c.

References DbgPrint, EXCEPTION_EXECUTE_HANDLER, _OBJECT_HANDLE_INFORMATION::GrantedAccess, Index, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObInsertObject(), ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, ProbeForRead, ProbeForWriteHandle, PTOKEN, SeCaptureLuidAndAttributesArray(), SeCaptureSidAndAttributesArray(), SepAcquireTokenReadLock, SepFilterToken(), SepReleaseTokenReadLock, SepTokenObjectType, SeReleaseLuidAndAttributesArray(), SeReleaseSidAndAttributesArray(), Status, Token, and TRUE.

Referenced by TestTokenFilter().

01317 : 01318 01319 Create a new token that is a subset of an existing token. 01320 01321 Arguments: 01322 01323 ExistingTokenHandle - Is a handle to a token already open for 01324 TOKEN_DUPLICATE access. 01325 01326 Flags - Flags indicating additional filtering. The flags may be: 01327 01328 DISABLE_ALL_GROUPS - disable all groups in token 01329 DELETE_ALL_PRIVILEGES - Disable all privileges 01330 01331 01332 SidsToDisable - Contains a list of sids and attributes. All sids with 01333 the USE_FOR_DENY_ONLY attribute that also exist in the token will 01334 cause the new token to have that sid set with the USE_FOR_DENY_ONLY 01335 attribte. 01336 01337 PrivilegesToDelete - Privileges in this list that are present in the 01338 existing token will not exist in the final token. This is similar 01339 to duplicating a token effective only with these privileges set to 01340 disabled. 01341 01342 RestrictedSids - Contains a list of SIDs and attributes that will be 01343 stored in the RestrictedSids field of the new token. These SIDs 01344 are used after a normal access check to futher restrict access. 01345 The attributes of these groups are always SE_GROUP_MANDATORY | 01346 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT. If there already 01347 exist RestrictedSids in the original token, these sids will be 01348 appended. 01349 01350 NewTokenHandle - Receives the handle of the newly created token. 01351 01352 Return Value: 01353 01354 STATUS_SUCCESS - Indicates the operation was successful. 01355 01356 STATUS_INVALID_PARAMETER - Indicates one or more of the parameter values 01357 was invalid. This value is returned if the target token is not 01358 an impersonation token. 01359 01360 01361 --*/ 01362 { 01363 01364 PTOKEN Token; 01365 PTOKEN NewToken; 01366 KPROCESSOR_MODE PreviousMode; 01367 NTSTATUS Status = STATUS_SUCCESS; 01368 01369 ULONG CapturedSidCount = 0; 01370 PSID_AND_ATTRIBUTES CapturedSids = NULL; 01371 ULONG CapturedSidsLength = 0; 01372 01373 ULONG CapturedGroupCount = 0; 01374 PSID_AND_ATTRIBUTES CapturedGroups = NULL; 01375 ULONG CapturedGroupsLength = 0; 01376 01377 ULONG CapturedPrivilegeCount = 0; 01378 PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL; 01379 ULONG CapturedPrivilegesLength = 0; 01380 ULONG Index; 01381 01382 HANDLE LocalHandle; 01383 01384 OBJECT_HANDLE_INFORMATION HandleInformation; 01385 ACCESS_MASK EffectiveDesiredAccess; 01386 01387 PAGED_CODE(); 01388 01389 PreviousMode = KeGetPreviousMode(); 01390 01391 // 01392 // Probe parameters 01393 // 01394 01395 01396 try { 01397 01398 01399 // 01400 // Make sure we can write the handle 01401 // 01402 01403 ProbeForWriteHandle(NewTokenHandle); 01404 01405 // 01406 // Capture Sids to remove 01407 // 01408 01409 if (ARGUMENT_PRESENT(SidsToDisable)) { 01410 ProbeForRead( SidsToDisable, sizeof(TOKEN_GROUPS), sizeof(ULONG) ); 01411 01412 CapturedGroupCount = SidsToDisable->GroupCount; 01413 Status = SeCaptureSidAndAttributesArray( 01414 SidsToDisable->Groups, 01415 CapturedGroupCount, 01416 PreviousMode, 01417 NULL, 0, 01418 PagedPool, 01419 TRUE, 01420 &CapturedGroups, 01421 &CapturedGroupsLength 01422 ); 01423 01424 } 01425 01426 // 01427 // Capture PrivilegesToDelete 01428 // 01429 01430 if (NT_SUCCESS(Status) && ARGUMENT_PRESENT(PrivilegesToDelete)) { 01431 ProbeForRead( PrivilegesToDelete, sizeof(TOKEN_PRIVILEGES), sizeof(ULONG) ); 01432 01433 CapturedPrivilegeCount = PrivilegesToDelete->PrivilegeCount; 01434 Status = SeCaptureLuidAndAttributesArray( 01435 PrivilegesToDelete->Privileges, 01436 CapturedPrivilegeCount, 01437 PreviousMode, 01438 NULL, 0, 01439 PagedPool, 01440 TRUE, 01441 &CapturedPrivileges, 01442 &CapturedPrivilegesLength 01443 ); 01444 01445 } 01446 01447 // 01448 // Capture Restricted Sids 01449 // 01450 01451 if (NT_SUCCESS(Status) && ARGUMENT_PRESENT(RestrictedSids)) { 01452 ProbeForRead( RestrictedSids, sizeof(TOKEN_GROUPS), sizeof(ULONG) ); 01453 01454 CapturedSidCount = RestrictedSids->GroupCount; 01455 Status = SeCaptureSidAndAttributesArray( 01456 RestrictedSids->Groups, 01457 CapturedSidCount, 01458 PreviousMode, 01459 NULL, 0, 01460 PagedPool, 01461 TRUE, 01462 &CapturedSids, 01463 &CapturedSidsLength 01464 ); 01465 01466 } 01467 01468 01469 01470 } except(EXCEPTION_EXECUTE_HANDLER) { 01471 01472 Status = GetExceptionCode(); 01473 } // end_try 01474 01475 if (!NT_SUCCESS(Status)) { 01476 goto Cleanup; 01477 } 01478 01479 // 01480 // Check that the attribtes are all zero for the restricted sids 01481 // 01482 01483 for (Index = 0; Index < CapturedSidCount ; Index++ ) 01484 { 01485 if (CapturedSids[Index].Attributes != 0) { 01486 Status = STATUS_INVALID_PARAMETER; 01487 goto Cleanup; 01488 } 01489 } 01490 // 01491 // Check the handle's access to the existing token and get 01492 // a pointer to that token. Pick up the default desired 01493 // access mask from the handle while we're at it. 01494 // 01495 01496 Status = ObReferenceObjectByHandle( 01497 ExistingTokenHandle, // Handle 01498 TOKEN_DUPLICATE, // DesiredAccess 01499 SepTokenObjectType, // ObjectType 01500 PreviousMode, // AccessMode 01501 (PVOID *)&Token, // Object 01502 &HandleInformation // GrantedAccess 01503 ); 01504 01505 if ( !NT_SUCCESS(Status) ) { 01506 01507 goto Cleanup; 01508 } 01509 01510 01511 #ifdef TOKEN_DEBUG 01512 01513 // 01514 // Debug 01515 SepAcquireTokenReadLock( Token ); 01516 DbgPrint("\n"); 01517 DbgPrint("\n"); 01518 DbgPrint("Token being filtered: \n"); 01519 SepDumpToken( Token ); 01520 SepReleaseTokenReadLock( Token ); 01521 // Debug 01522 // 01524 #endif //TOKEN_DEBUG 01525 01526 01527 // 01528 // Check to see if an alternate desired access mask was provided. 01529 // 01530 01531 01532 EffectiveDesiredAccess = HandleInformation.GrantedAccess; 01533 01534 01535 01536 // 01537 // Filter the existing token 01538 // 01539 01540 NewToken = NULL; 01541 Status = SepFilterToken( 01542 Token, 01543 PreviousMode, 01544 Flags, 01545 CapturedGroupCount, 01546 CapturedGroups, 01547 CapturedPrivilegeCount, 01548 CapturedPrivileges, 01549 CapturedSidCount, 01550 CapturedSids, 01551 CapturedSidsLength, 01552 &NewToken 01553 ); 01554 01555 01556 if (NT_SUCCESS(Status)) { 01557 01558 // 01559 // Insert the new token 01560 // 01561 01562 Status = ObInsertObject( NewToken, 01563 NULL, 01564 EffectiveDesiredAccess, 01565 0, 01566 (PVOID *)NULL, 01567 &LocalHandle 01568 ); 01569 01570 if (!NT_SUCCESS( Status )) { 01571 #ifdef TOKEN_DEBUG 01572 DbgPrint( "SE: ObInsertObject failed (%x) for token at %x\n", Status, NewToken ); 01573 #endif 01574 } 01575 01576 } else 01577 if (NewToken != NULL) { 01578 #ifdef TOKEN_DEBUG 01579 DbgPrint( "SE: SepFilterToken failed (%x) but allocated token at %x\n", Status, NewToken ); 01580 #endif 01581 } 01582 01583 // 01584 // We no longer need our reference to the source token 01585 // 01586 01587 ObDereferenceObject( (PVOID)Token ); 01588 01589 01590 // BUGWARNING Probably need to audit here 01591 01592 // 01593 // Return the new handle 01594 // 01595 01596 if (NT_SUCCESS(Status)) { 01597 try { *NewTokenHandle = LocalHandle; } 01598 except(EXCEPTION_EXECUTE_HANDLER) { 01599 Status = GetExceptionCode(); 01600 } 01601 } 01602 01603 Cleanup: 01604 01605 if (CapturedGroups != NULL) { 01606 SeReleaseSidAndAttributesArray( 01607 CapturedGroups, 01608 PreviousMode, 01609 TRUE 01610 ); 01611 } 01612 01613 if (CapturedPrivileges != NULL) { 01614 SeReleaseLuidAndAttributesArray( 01615 CapturedPrivileges, 01616 PreviousMode, 01617 TRUE 01618 ); 01619 } 01620 01621 if (CapturedSids != NULL) { 01622 SeReleaseSidAndAttributesArray( 01623 CapturedSids, 01624 PreviousMode, 01625 TRUE 01626 ); 01627 } 01628 01629 return Status; 01630 }

NTSTATUS SeCopyClientToken IN PACCESS_TOKEN  ClientToken,
IN SECURITY_IMPERSONATION_LEVEL  ImpersonationLevel,
IN KPROCESSOR_MODE  RequestorMode,
OUT PACCESS_TOKEN *  DuplicateToken
 

Definition at line 1227 of file tokendup.c.

References ClientToken, FALSE, NTSTATUS(), NULL, ObjectAttributes, PAGED_CODE, PTOKEN, SepDuplicateToken(), and Status.

Referenced by SepCreateClientSecurity().

01237 : 01238 01239 This routine copies a client's token as part of establishing a client 01240 context for impersonation. 01241 01242 The result will be an impersonation token. 01243 01244 No handles to the new token are established. 01245 01246 The token will be an exact duplicate of the source token. It is the 01247 caller's responsibility to ensure an effective only copy of the token 01248 is produced when the token is opened, if necessary. 01249 01250 01251 Arguments: 01252 01253 ClientToken - Points to the token to be duplicated. This may be either 01254 a primary or impersonation token. 01255 01256 ImpersonationLevel - The impersonation level to be assigned to the new 01257 token. 01258 01259 RequestorMode - Mode to be assigned as the owner mode of the new token. 01260 01261 DuplicateToken - Receives a pointer to the duplicate token. 01262 The token has not yet been inserted into any object table. 01263 No exceptions are expected when tring to set this OUT value. 01264 01265 Return Value: 01266 01267 STATUS_SUCCESS - The service successfully completed the requested 01268 operation. 01269 01270 01271 --*/ 01272 { 01273 NTSTATUS Status; 01274 OBJECT_ATTRIBUTES ObjectAttributes; 01275 PTOKEN NewToken; 01276 01277 PAGED_CODE(); 01278 01279 InitializeObjectAttributes( 01280 &ObjectAttributes, 01281 NULL, 01282 0, 01283 NULL, 01284 NULL 01285 ); 01286 01287 Status = SepDuplicateToken( 01288 (PTOKEN)ClientToken, // ExistingToken 01289 &ObjectAttributes, // ObjectAttributes 01290 FALSE, // EffectiveOnly 01291 TokenImpersonation, // TokenType (target) 01292 ImpersonationLevel, // ImpersonationLevel 01293 RequestorMode, // RequestorMode 01294 &NewToken // DuplicateToken 01295 ); 01296 01297 (*DuplicateToken) = (PACCESS_TOKEN)NewToken; 01298 01299 return Status; 01300 01301 }

NTSTATUS SeFastFilterToken IN PACCESS_TOKEN  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 PACCESS_TOKEN *  FilteredToken
 

Definition at line 1859 of file tokendup.c.

References PTOKEN, and SepFilterToken().

Referenced by PsAssignImpersonationToken(), and PsImpersonateClient().

01874 : 01875 01876 This is a fast wrapper for the Ps code to filter a token 01877 inline of an impersonate. 01878 01879 This routine acquires a read lock on the token being filtered. 01880 01881 Arguments: 01882 01883 ExistingToken - Points to the token to be duplicated. 01884 01885 GroupCount - Count of groups to disable 01886 01887 GroupsToDisable - Contains a list of sids and attributes. All sids with 01888 the USE_FOR_DENY_ONLY attribute that also exist in the token will 01889 cause the new token to have that sid set with the USE_FOR_DENY_ONLY 01890 attribute. 01891 01892 PrivilegeCount - Count of privileges to delete 01893 01894 PrivilegesToDelete - Privileges in this list that are present in the 01895 existing token will not exist in the final token. This is similar 01896 to duplicating a token effective only with these privileges set to 01897 disabled. 01898 01899 SidCount - Count of restricted sids to add. 01900 01901 RestrictedSids - Contains a list of SIDs and attributes that will be 01902 stored in the RestrictedSids field of the new token. These SIDs 01903 are used after a normal access check to futher restrict access. 01904 The attributes of these groups are always SE_GROUP_MANDATORY | 01905 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT. If there already 01906 exist RestrictedSids in the original token, these sids will be 01907 appended. 01908 01909 SidLength - Length of added restricted sids. 01910 01911 FilteredToken - Receives a pointer to the duplicate token. 01912 The token has not yet been inserted into any object table. 01913 No exceptions are expected when tring to set this OUT value. 01914 01915 Return Value: 01916 01917 STATUS_SUCCESS - The service successfully completed the requested 01918 operation. 01919 01920 01921 --*/ 01922 { 01923 return SepFilterToken( (PTOKEN) ExistingToken, 01924 RequestorMode, 01925 Flags, 01926 GroupCount, 01927 GroupsToDisable, 01928 PrivilegeCount, 01929 PrivilegesToDelete, 01930 SidCount, 01931 RestrictedSids, 01932 SidLength, 01933 (PTOKEN *) FilteredToken ); 01934 }

NTSTATUS SeFilterToken IN PACCESS_TOKEN  ExistingToken,
IN ULONG  Flags,
IN PTOKEN_GROUPS SidsToDisable  OPTIONAL,
IN PTOKEN_PRIVILEGES PrivilegesToDelete  OPTIONAL,
IN PTOKEN_GROUPS RestrictedSids  OPTIONAL,
OUT PACCESS_TOKEN *  NewToken
 

Definition at line 1634 of file tokendup.c.

References DbgPrint, Index, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NtClose(), NTSTATUS(), NULL, ObInsertObject(), ObReferenceObjectByHandle(), PAGED_CODE, PTOKEN, SepAcquireTokenReadLock, SepFilterToken(), SepReleaseTokenReadLock, SepTokenObjectType, Status, Token, and VOID().

01645 : 01646 01647 Create a new token that is a subset of an existing token. 01648 01649 Arguments: 01650 01651 ExistingToken - Is a token already open for 01652 TOKEN_DUPLICATE access. 01653 01654 Flags - Flags indicating additional filtering. The flags may be: 01655 01656 DISABLE_ALL_GROUPS - disable all groups in token 01657 DELETE_ALL_PRIVILEGES - Disable all privileges 01658 01659 01660 SidsToDisable - Contains a list of sids and attributes. All sids with 01661 the USE_FOR_DENY_ONLY attribute that also exist in the token will 01662 cause the new token to have that sid set with the USE_FOR_DENY_ONLY 01663 attribte. 01664 01665 PrivilegesToDelete - Privileges in this list that are present in the 01666 existing token will not exist in the final token. This is similar 01667 to duplicating a token effective only with these privileges set to 01668 disabled. 01669 01670 RestrictedSids - Contains a list of SIDs and attributes that will be 01671 stored in the RestrictedSids field of the new token. These SIDs 01672 are used after a normal access check to futher restrict access. 01673 The attributes of these groups are always SE_GROUP_MANDATORY | 01674 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT. If there already 01675 exist RestrictedSids in the original token, these sids will be 01676 appended. 01677 01678 NewToken - Receives a pointer to the newly created token. 01679 01680 Return Value: 01681 01682 STATUS_SUCCESS - Indicates the operation was successful. 01683 01684 STATUS_INVALID_PARAMETER - Indicates one or more of the parameter values 01685 was invalid. This value is returned if the target token is not 01686 an impersonation token. 01687 01688 01689 --*/ 01690 { 01691 01692 PTOKEN Token; 01693 PTOKEN FilteredToken = NULL; 01694 KPROCESSOR_MODE PreviousMode; 01695 NTSTATUS Status = STATUS_SUCCESS; 01696 ULONG Index; 01697 01698 ULONG CapturedSidCount = 0; 01699 PSID_AND_ATTRIBUTES CapturedSids = NULL; 01700 ULONG CapturedSidsLength = 0; 01701 01702 ULONG CapturedGroupCount = 0; 01703 PSID_AND_ATTRIBUTES CapturedGroups = NULL; 01704 ULONG CapturedGroupsLength = 0; 01705 01706 ULONG CapturedPrivilegeCount = 0; 01707 PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL; 01708 ULONG CapturedPrivilegesLength = 0; 01709 01710 HANDLE LocalHandle; 01711 01712 OBJECT_HANDLE_INFORMATION HandleInformation; 01713 ACCESS_MASK EffectiveDesiredAccess; 01714 01715 PAGED_CODE(); 01716 01717 PreviousMode = KeGetPreviousMode(); 01718 01719 // 01720 // Probe parameters 01721 // 01722 01723 *NewToken = NULL; 01724 01725 01726 // 01727 // Capture Sids to remove 01728 // 01729 01730 if (ARGUMENT_PRESENT(SidsToDisable)) { 01731 01732 CapturedGroupCount = SidsToDisable->GroupCount; 01733 CapturedGroups = SidsToDisable->Groups; 01734 01735 } 01736 01737 // 01738 // Capture PrivilegesToDelete 01739 // 01740 01741 if (ARGUMENT_PRESENT(PrivilegesToDelete)) { 01742 01743 CapturedPrivilegeCount = PrivilegesToDelete->PrivilegeCount; 01744 CapturedPrivileges = PrivilegesToDelete->Privileges; 01745 01746 } 01747 01748 // 01749 // Capture Restricted Sids 01750 // 01751 01752 if (ARGUMENT_PRESENT(RestrictedSids)) { 01753 01754 CapturedSidCount = RestrictedSids->GroupCount; 01755 CapturedSids = RestrictedSids->Groups; 01756 01757 // 01758 // Check that the attribtes are all zero for the restricted sids 01759 // 01760 01761 for (Index = 0; Index < CapturedSidCount ; Index++ ) { 01762 if (CapturedSids[Index].Attributes != 0) { 01763 return(STATUS_INVALID_PARAMETER); 01764 } 01765 } 01766 01767 } 01768 01769 01770 01771 // 01772 // Check the handle's access to the existing token and get 01773 // a pointer to that token. Pick up the default desired 01774 // access mask from the handle while we're at it. 01775 // 01776 01777 Token = (PTOKEN) ExistingToken; 01778 01779 01780 #ifdef TOKEN_DEBUG 01781 01782 // 01783 // Debug 01784 SepAcquireTokenReadLock( Token ); 01785 DbgPrint("\n"); 01786 DbgPrint("\n"); 01787 DbgPrint("Token being filtered: \n"); 01788 SepDumpToken( Token ); 01789 SepReleaseTokenReadLock( Token ); 01790 // Debug 01791 // 01793 #endif //TOKEN_DEBUG 01794 01795 01796 // 01797 // Filter the existing token 01798 // 01799 01800 Status = SepFilterToken( 01801 Token, 01802 KernelMode, 01803 Flags, 01804 CapturedGroupCount, 01805 CapturedGroups, 01806 CapturedPrivilegeCount, 01807 CapturedPrivileges, 01808 CapturedSidCount, 01809 CapturedSids, 01810 CapturedSidsLength, 01811 &FilteredToken 01812 ); 01813 01814 01815 if (NT_SUCCESS(Status)) { 01816 01817 // 01818 // Insert the new token 01819 // 01820 01821 Status = ObInsertObject( FilteredToken, 01822 NULL, 01823 0, 01824 0, 01825 (PVOID *)NULL, 01826 &LocalHandle 01827 ); 01828 01829 if (!NT_SUCCESS( Status )) { 01830 #ifdef TOKEN_DEBUG 01831 DbgPrint( "SE: ObInsertObject failed (%x) for token at %x\n", Status, NewToken ); 01832 #endif 01833 } else { 01834 Status = ObReferenceObjectByHandle( 01835 LocalHandle, 01836 TOKEN_IMPERSONATE, 01837 SepTokenObjectType, 01838 KernelMode, 01839 (PVOID * ) NewToken, 01840 NULL // granted acess 01841 ); 01842 01843 (VOID) NtClose(LocalHandle); 01844 01845 } 01846 01847 } else if (NewToken != NULL) { 01848 #ifdef TOKEN_DEBUG 01849 DbgPrint( "SE: SepFilterToken failed (%x) but allocated token at %x\n", Status, NewToken ); 01850 #endif 01851 } 01852 01853 01854 01855 return Status; 01856 }

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

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 }


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