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

tokenadj.c File Reference

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

Go to the source code of this file.

Functions

NTSTATUS NtAdjustPrivilegesToken (IN HANDLE TokenHandle, IN BOOLEAN DisableAllPrivileges, IN PTOKEN_PRIVILEGES NewState OPTIONAL, IN ULONG BufferLength OPTIONAL, OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PULONG ReturnLength)
NTSTATUS NtAdjustGroupsToken (IN HANDLE TokenHandle, IN BOOLEAN ResetToDefault, IN PTOKEN_GROUPS NewState OPTIONAL, IN ULONG BufferLength OPTIONAL, OUT PTOKEN_GROUPS PreviousState OPTIONAL, OUT PULONG ReturnLength)
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)
NTSTATUS SepAdjustGroups (IN PTOKEN Token, IN BOOLEAN MakeChanges, IN BOOLEAN ResetToDefault, IN ULONG GroupCount, IN PSID_AND_ATTRIBUTES NewState OPTIONAL, OUT PTOKEN_GROUPS PreviousState OPTIONAL, OUT PSID SidBuffer OPTIONAL, OUT PULONG ReturnLength, OUT PULONG ChangeCount, OUT PBOOLEAN ChangesMade)


Function Documentation

NTSTATUS NtAdjustGroupsToken IN HANDLE  TokenHandle,
IN BOOLEAN  ResetToDefault,
IN PTOKEN_GROUPS NewState  OPTIONAL,
IN ULONG BufferLength  OPTIONAL,
OUT PTOKEN_GROUPS PreviousState  OPTIONAL,
OUT PULONG  ReturnLength
 

Definition at line 432 of file tokenadj.c.

References ANYSIZE_ARRAY, ChangesMade, EXCEPTION_EXECUTE_HANDLER, FALSE, KernelMode, KPROCESSOR_MODE, LongAlignPtr, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, ProbeForRead, ProbeForWrite(), ProbeForWriteUlong, PTOKEN, SeCaptureSidAndAttributesArray(), SepAcquireTokenWriteLock, SepAdjustGroups(), SepReleaseTokenWriteLock, SepTokenObjectType, SeReleaseSidAndAttributesArray(), Status, Token, and TRUE.

Referenced by TestTokenAdjustGroups().

00444 : 00445 00446 This routine is used to disable or enable groups in the specified 00447 token. The absence of some of the groups listed to be changed 00448 won't effect the successful modification of the groups that are in 00449 the token. The previous enabled/disabled state of changed groups 00450 may optionally be capture (for resetting later). 00451 00452 TOKEN_ADJUST_GROUPS access is required to enable or disable groups 00453 in a token 00454 00455 Note that mandatory groups can not be disabled. An attempt 00456 disable any mandatory groups will cause the call to fail, leaving 00457 the state of all groups unchanged. 00458 00459 00460 Arguments: 00461 00462 TokenHandle - Provides a handle to the token to operate on. 00463 00464 ResetToDefault - The parameter indicates whether all the groups 00465 in the token are to be reset to their default enabled/disabled 00466 state. 00467 00468 NewState - This parameter points to a TOKEN_GROUPS data structure 00469 containing the groups whose states are to be adjusted 00470 (disabled or enabled). Only the Enabled flag of the 00471 attributes associated with each group is used. It provides 00472 the new value that is to be assigned to the group in the 00473 token. If the ResetToDefault argument is specified as TRUE, 00474 then this argument is ignored. Otherwise, it must be passed. 00475 00476 BufferLength - This optional parameter indicates the length (in 00477 bytes) of the PreviousState buffer. This value must be 00478 provided if the PreviousState parameter is provided. 00479 00480 PreviousState - This (optional) parameter points to a buffer to 00481 receive the state of any groups actually changed by this 00482 request. This information is formated as a TOKEN_GROUPS data 00483 structure which may be passed as the NewState parameter in a 00484 subsequent call to NtAdjustGroups to restore the original state 00485 of those groups. TOKEN_QUERY access is needed to use this 00486 parameter. 00487 00488 If this buffer does not contain enough space to receive the 00489 complete list of modified groups, then no group states are 00490 changed and STATUS_BUFFER_TOO_SMALL is returned. In this 00491 case, the ReturnLength return parameter will contain the 00492 actual number of bytes needed to hold the information. 00493 00494 ReturnLength - Indicates the actual number of bytes needed to 00495 contain the previous group state information. 00496 This parameter is ignored if the PreviousState argument is not 00497 passed. 00498 00499 00500 Return Value: 00501 00502 STATUS_SUCCESS - The service successfully completed the requested 00503 operation. 00504 00505 STATUS_NOT_ALL_ASSIGNED - This NT_SUCCESS severity return status 00506 indicates that not all the specified groups are currently 00507 assigned to the caller. All specified groups that are 00508 currently assigned have been successfully adjusted. 00509 00510 STATUS_CANT_DISABLE_MANDATORY - Indicates an attempt was made to 00511 disable a mandatory group. The states of all groups remains 00512 unchanged. 00513 00514 STATUS_BUFFER_TOO_SMALL - Indicates the optional buffer provided 00515 to receive the previous states of changed group wasn't large 00516 enough to receive that information. No changes to group 00517 states has been made. The number of bytes needed to hold the 00518 state change information is returned via the ReturnLength 00519 parameter. 00520 00521 STATUS_INVALID_PARAMETER - Indicates neither the ResetToDefault 00522 parameter was specified as true, nor was an explicit NewState 00523 provided. 00524 00525 --*/ 00526 { 00527 00528 KPROCESSOR_MODE PreviousMode; 00529 NTSTATUS Status; 00530 00531 PTOKEN Token; 00532 00533 ACCESS_MASK DesiredAccess; 00534 00535 ULONG CapturedGroupCount; 00536 PSID_AND_ATTRIBUTES CapturedGroups = NULL; 00537 ULONG CapturedGroupsLength; 00538 00539 ULONG LocalReturnLength; 00540 ULONG ChangeCount; 00541 BOOLEAN ChangesMade; 00542 PSID SidBuffer; 00543 00544 PAGED_CODE(); 00545 00546 // 00547 // The semantics of the PreviousState parameter and the 00548 // STATUS_CANT_DISABLE_MANDATORY completion status leads to a two-pass 00549 // approach to adjusting groups. The first pass simply checks 00550 // to see which groups will change and counts them. This allows 00551 // the amount of space needed to be calculated and returned. If 00552 // the caller's PreviousState return buffer is not large enough, or 00553 // one of the specified groups is a mandatory group, then an error 00554 // is returned without making any modifications. Otherwise, a second 00555 // pass is made to actually make the changes. 00556 // 00557 00558 if (!ResetToDefault && !ARGUMENT_PRESENT(NewState)) { 00559 return STATUS_INVALID_PARAMETER; 00560 } 00561 00562 // 00563 // Get previous processor mode and probe parameters if necessary. 00564 // 00565 00566 PreviousMode = KeGetPreviousMode(); 00567 if (PreviousMode != KernelMode) { 00568 try { 00569 00570 if (!ResetToDefault) { 00571 ProbeForRead( 00572 NewState, 00573 sizeof(TOKEN_GROUPS), 00574 sizeof(ULONG) 00575 ); 00576 } 00577 00578 if (ARGUMENT_PRESENT(PreviousState)) { 00579 00580 ProbeForWrite( 00581 PreviousState, 00582 BufferLength, 00583 sizeof(ULONG) 00584 ); 00585 00586 // 00587 // This parameter is only used if PreviousState 00588 // is present 00589 // 00590 00591 ProbeForWriteUlong(ReturnLength); 00592 00593 } 00594 00595 00596 } except(EXCEPTION_EXECUTE_HANDLER) { 00597 return GetExceptionCode(); 00598 } 00599 } 00600 00601 // 00602 // Capture NewState. 00603 // 00604 00605 if (!ResetToDefault) { 00606 00607 try { 00608 00609 CapturedGroupCount = NewState->GroupCount; 00610 Status = SeCaptureSidAndAttributesArray( 00611 &(NewState->Groups[0]), 00612 CapturedGroupCount, 00613 PreviousMode, 00614 NULL, 0, 00615 PagedPool, 00616 TRUE, 00617 &CapturedGroups, 00618 &CapturedGroupsLength 00619 ); 00620 00621 if (!NT_SUCCESS(Status)) { 00622 00623 return Status; 00624 00625 } 00626 00627 } except(EXCEPTION_EXECUTE_HANDLER) { 00628 00629 return GetExceptionCode(); 00630 00631 } // endtry 00632 } // endif !ResetToDefault 00633 00634 00635 // 00636 // Reference the token object and validate the caller's right 00637 // to adjust the groups. 00638 // 00639 00640 if (ARGUMENT_PRESENT(PreviousState)) { 00641 DesiredAccess = (TOKEN_ADJUST_GROUPS | TOKEN_QUERY); 00642 } else { 00643 DesiredAccess = TOKEN_ADJUST_GROUPS; 00644 } 00645 00646 Status = ObReferenceObjectByHandle( 00647 TokenHandle, // Handle 00648 DesiredAccess, // DesiredAccess 00649 SepTokenObjectType, // ObjectType 00650 PreviousMode, // AccessMode 00651 (PVOID *)&Token, // Object 00652 NULL // GrantedAccess 00653 ); 00654 00655 if ( !NT_SUCCESS(Status) ) { 00656 00657 if (ARGUMENT_PRESENT(CapturedGroups)) { 00658 SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE ); 00659 } 00660 00661 return Status; 00662 } 00663 00664 // 00665 // Gain exclusive access to the token. 00666 // 00667 00668 SepAcquireTokenWriteLock( Token ); 00669 00670 // 00671 // First pass through the groups list. 00672 // 00673 // This pass is always necessary for groups to make sure the caller 00674 // isn't trying to do anything illegal to mandatory groups. 00675 // 00676 00677 Status = SepAdjustGroups( 00678 Token, 00679 FALSE, // Don't make changes this pass 00680 ResetToDefault, 00681 CapturedGroupCount, 00682 CapturedGroups, 00683 PreviousState, 00684 NULL, // Not returning SIDs this call 00685 &LocalReturnLength, 00686 &ChangeCount, 00687 &ChangesMade 00688 ); 00689 00690 if (ARGUMENT_PRESENT(PreviousState)) { 00691 00692 try { 00693 00694 (*ReturnLength) = LocalReturnLength; 00695 00696 } except(EXCEPTION_EXECUTE_HANDLER) { 00697 00698 SepReleaseTokenWriteLock( Token, FALSE ); 00699 ObDereferenceObject( Token ); 00700 00701 if (ARGUMENT_PRESENT(CapturedGroups)) { 00702 SeReleaseSidAndAttributesArray( 00703 CapturedGroups, 00704 PreviousMode, 00705 TRUE 00706 ); 00707 } 00708 00709 return GetExceptionCode(); 00710 } 00711 } 00712 00713 // 00714 // Make sure we didn't encounter an error 00715 // 00716 00717 if (!NT_SUCCESS(Status)) { 00718 00719 SepReleaseTokenWriteLock( Token, FALSE ); 00720 ObDereferenceObject( Token ); 00721 00722 if (ARGUMENT_PRESENT(CapturedGroups)) { 00723 SeReleaseSidAndAttributesArray( 00724 CapturedGroups, 00725 PreviousMode, 00726 TRUE 00727 ); 00728 } 00729 00730 return Status; 00731 00732 } 00733 00734 // 00735 // Make sure there is enough room to return requested information. 00736 // Also go on to calculate where the SID values go. 00737 // 00738 00739 if (ARGUMENT_PRESENT(PreviousState)) { 00740 if (LocalReturnLength > BufferLength) { 00741 00742 SepReleaseTokenWriteLock( Token, FALSE ); 00743 ObDereferenceObject( Token ); 00744 00745 if (ARGUMENT_PRESENT(CapturedGroups)) { 00746 SeReleaseSidAndAttributesArray( 00747 CapturedGroups, 00748 PreviousMode, 00749 TRUE 00750 ); 00751 } 00752 00753 00754 return STATUS_BUFFER_TOO_SMALL; 00755 } 00756 00757 // 00758 // Calculate where the SIDs can be placed in the PreviousState 00759 // buffer. 00760 // 00761 00762 SidBuffer = (PSID)(LongAlignPtr( 00763 (PCHAR)PreviousState + (ULONG)sizeof(TOKEN_GROUPS) + 00764 (ChangeCount * (ULONG)sizeof(SID_AND_ATTRIBUTES)) - 00765 (ANYSIZE_ARRAY * (ULONG)sizeof(SID_AND_ATTRIBUTES)) 00766 ) ); 00767 00768 } 00769 00770 // 00771 // Second pass through the groups list. 00772 // 00773 00774 try { 00775 00776 Status = SepAdjustGroups( 00777 Token, 00778 TRUE, // Make changes in this pass 00779 ResetToDefault, 00780 CapturedGroupCount, 00781 CapturedGroups, 00782 PreviousState, 00783 SidBuffer, 00784 &LocalReturnLength, 00785 &ChangeCount, 00786 &ChangesMade 00787 ); 00788 00789 if (ARGUMENT_PRESENT(PreviousState)) { 00790 00791 PreviousState->GroupCount = ChangeCount; 00792 } 00793 00794 } except(EXCEPTION_EXECUTE_HANDLER) { 00795 00796 //SepFreeToken( Token, TRUE ); 00797 SepReleaseTokenWriteLock( Token, TRUE ); 00798 ObDereferenceObject( Token ); 00799 if (ARGUMENT_PRESENT(CapturedGroups)) { 00800 SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE ); 00801 } 00802 return GetExceptionCode(); 00803 00804 } 00805 00806 //SepFreeToken( Token, ChangesMade ); 00807 SepReleaseTokenWriteLock( Token, ChangesMade ); 00808 ObDereferenceObject( Token ); 00809 00810 if (ARGUMENT_PRESENT(CapturedGroups)) { 00811 SeReleaseSidAndAttributesArray( CapturedGroups, PreviousMode, TRUE ); 00812 } 00813 00814 return Status; 00815 00816 }

NTSTATUS NtAdjustPrivilegesToken IN HANDLE  TokenHandle,
IN BOOLEAN  DisableAllPrivileges,
IN PTOKEN_PRIVILEGES NewState  OPTIONAL,
IN ULONG BufferLength  OPTIONAL,
OUT PTOKEN_PRIVILEGES PreviousState  OPTIONAL,
OUT PULONG  ReturnLength
 

Definition at line 46 of file tokenadj.c.

References ANYSIZE_ARRAY, ChangesMade, DisableAllPrivileges(), EXCEPTION_EXECUTE_HANDLER, FALSE, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, PagedPool, ProbeForRead, ProbeForWrite(), ProbeForWriteUlong, PTOKEN, SeCaptureLuidAndAttributesArray(), SepAcquireTokenWriteLock, SepAdjustPrivileges(), SepReleaseTokenWriteLock, SepTokenObjectType, SeReleaseLuidAndAttributesArray(), Status, Token, and TRUE.

Referenced by DisableAllPrivileges(), EnableAllPrivileges(), ResetAllPrivileges(), RtlAdjustPrivilege(), TestTokenAdjustPrivileges(), and TestTokenInitialize().

00059 : 00060 00061 This routine is used to disable or enable privileges in the 00062 specified token. The absence of some of the privileges listed to 00063 be changed won't effect the successful modification of the 00064 privileges that are in the token. The previous enabled/disabled 00065 state of changed privileges may optionally be capture (for 00066 resetting later). 00067 00068 TOKEN_ADJUST_PRIVILEGES access is required to enable or disable 00069 privileges in a token. 00070 00071 00072 Arguments: 00073 00074 TokenHandle - Provides a handle to the token to operate on. 00075 00076 DisableAllPrivileges - This boolean parameter may be 00077 used to disable all privileges assigned to the token. If 00078 this parameter is specified as TRUE, then the NewState parameter is 00079 ignored. 00080 00081 NewState - This (optional) parameter points to a TOKEN_PRIVILEGES 00082 data structure containing the privileges whose states are to 00083 be adjusted (disabled or enabled). Only the Enabled flag of 00084 the attributes associated with each privilege is used. It 00085 provides the new value that is to be assigned to the 00086 privilege in the token. 00087 00088 BufferLength - This optional parameter indicates the length (in 00089 bytes) of the PreviousState buffer. This value must be 00090 provided if the PreviousState parameter is provided. 00091 00092 PreviousState - This (optional) parameter points to a buffer to 00093 receive the state of any privileges actually changed by this 00094 request. This information is formated as a TOKEN_PRIVILEGES 00095 data structure which may be passed as the NewState parameter 00096 in a subsequent call to this routine to restore the original 00097 state of those privilges. TOKEN_QUERY access is needed to 00098 use this parameter. 00099 00100 If this buffer does not contain enough space to receive the 00101 complete list of modified privileges, then no privilege 00102 states are changed and STATUS_BUFFER_TOO_SMALL is returned. 00103 In this case, the ReturnLength OUT parameter will 00104 contain the actual number of bytes needed to hold the 00105 information. 00106 00107 ReturnLength - Indicates the actual number of bytes needed to 00108 contain the previous privilege state information. 00109 This parameter is ignored if the PreviousState argument is not 00110 passed. 00111 00112 Return Value: 00113 00114 STATUS_SUCCESS - The service successfully completed the requested 00115 operation. 00116 00117 STATUS_NOT_ALL_ASSIGNED - This NT_SUCCESS severity return status 00118 indicates that not all the specified privileges are currently 00119 assigned to the caller. All specified privileges that are 00120 currently assigned have been successfully adjusted. 00121 00122 STATUS_BUFFER_TOO_SMALL - Indicates the optional buffer provided 00123 to receive the previous states of changed privileges wasn't 00124 large enough to receive that information. No changes to 00125 privilege states has been made. The number of bytes needed 00126 to hold the state change information is returned via the 00127 ReturnLength parameter. 00128 00129 STATUS_INVALID_PARAMETER - Indicates neither the DisableAllPrivileges 00130 parameter was specified as true, nor was an explicit NewState 00131 provided. 00132 00133 --*/ 00134 00135 { 00136 KPROCESSOR_MODE PreviousMode; 00137 NTSTATUS Status; 00138 00139 PTOKEN Token; 00140 00141 ACCESS_MASK DesiredAccess; 00142 00143 ULONG CapturedPrivilegeCount; 00144 PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL; 00145 ULONG CapturedPrivilegesLength; 00146 00147 ULONG LocalReturnLength; 00148 ULONG ChangeCount; 00149 BOOLEAN ChangesMade; 00150 00151 ULONG ParameterLength; 00152 00153 PAGED_CODE(); 00154 00155 // 00156 // The semantics of the PreviousState parameter leads to a two-pass 00157 // approach to adjusting privileges. The first pass simply checks 00158 // to see which privileges will change and counts them. This allows 00159 // the amount of space needed to be calculated and returned. If 00160 // the caller's PreviousState return buffer is not large enough, then 00161 // an error is returned without making any modifications. Otherwise, 00162 // a second pass is made to actually make the changes. 00163 // 00164 // 00165 00166 if (!DisableAllPrivileges && !ARGUMENT_PRESENT(NewState)) { 00167 return STATUS_INVALID_PARAMETER; 00168 } 00169 00170 // 00171 // Get previous processor mode and probe parameters if necessary. 00172 // 00173 00174 PreviousMode = KeGetPreviousMode(); 00175 if (PreviousMode != KernelMode) { 00176 try { 00177 00178 // 00179 // Make sure we can see all of the new state 00180 // 00181 00182 if (!DisableAllPrivileges) { 00183 00184 ProbeForRead( 00185 NewState, 00186 sizeof(TOKEN_PRIVILEGES), 00187 sizeof(ULONG) 00188 ); 00189 00190 CapturedPrivilegeCount = NewState->PrivilegeCount; 00191 ParameterLength = (ULONG)sizeof(TOKEN_PRIVILEGES) + 00192 ( (CapturedPrivilegeCount - ANYSIZE_ARRAY) * 00193 (ULONG)sizeof(LUID_AND_ATTRIBUTES) ); 00194 00195 ProbeForRead( 00196 NewState, 00197 ParameterLength, 00198 sizeof(ULONG) 00199 ); 00200 00201 } 00202 00203 00204 // 00205 // Check the PreviousState buffer for writeability 00206 // 00207 00208 if (ARGUMENT_PRESENT(PreviousState)) { 00209 00210 ProbeForWrite( 00211 PreviousState, 00212 BufferLength, 00213 sizeof(ULONG) 00214 ); 00215 00216 ProbeForWriteUlong(ReturnLength); 00217 } 00218 00219 00220 } except(EXCEPTION_EXECUTE_HANDLER) { 00221 return GetExceptionCode(); 00222 } 00223 00224 } else { 00225 00226 if (!DisableAllPrivileges) { 00227 00228 CapturedPrivilegeCount = NewState->PrivilegeCount; 00229 } 00230 } 00231 00232 00233 00234 // 00235 // Capture NewState if passed. 00236 // 00237 00238 if (!DisableAllPrivileges) { 00239 00240 try { 00241 00242 00243 Status = SeCaptureLuidAndAttributesArray( 00244 (NewState->Privileges), 00245 CapturedPrivilegeCount, 00246 PreviousMode, 00247 NULL, 0, 00248 PagedPool, 00249 TRUE, 00250 &CapturedPrivileges, 00251 &CapturedPrivilegesLength 00252 ); 00253 00254 } except(EXCEPTION_EXECUTE_HANDLER) { 00255 00256 return GetExceptionCode(); 00257 00258 } 00259 00260 if (!NT_SUCCESS(Status)) { 00261 00262 return Status; 00263 00264 } 00265 00266 } 00267 00268 00269 // 00270 // Reference the token object and validate the caller's right 00271 // to adjust the privileges. 00272 // 00273 00274 if (ARGUMENT_PRESENT(PreviousState)) { 00275 DesiredAccess = (TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY); 00276 } else { 00277 DesiredAccess = TOKEN_ADJUST_PRIVILEGES; 00278 } 00279 00280 Status = ObReferenceObjectByHandle( 00281 TokenHandle, // Handle 00282 DesiredAccess, // DesiredAccess 00283 SepTokenObjectType, // ObjectType 00284 PreviousMode, // AccessMode 00285 (PVOID *)&Token, // Object 00286 NULL // GrantedAccess 00287 ); 00288 00289 if ( !NT_SUCCESS(Status) ) { 00290 00291 if (CapturedPrivileges != NULL) { 00292 SeReleaseLuidAndAttributesArray( 00293 CapturedPrivileges, 00294 PreviousMode, 00295 TRUE 00296 ); 00297 } 00298 00299 return Status; 00300 } 00301 00302 // 00303 // Gain exclusive access to the token. 00304 // 00305 00306 SepAcquireTokenWriteLock( Token ); 00307 00308 // 00309 // First pass through the privileges list - just count the changes 00310 // 00311 00312 00313 Status = SepAdjustPrivileges( 00314 Token, 00315 FALSE, // Don't make changes this pass 00316 DisableAllPrivileges, 00317 CapturedPrivilegeCount, 00318 CapturedPrivileges, 00319 PreviousState, 00320 &LocalReturnLength, 00321 &ChangeCount, 00322 &ChangesMade 00323 ); 00324 00325 if (ARGUMENT_PRESENT(PreviousState)) { 00326 00327 try { 00328 00329 (*ReturnLength) = LocalReturnLength; 00330 00331 } except(EXCEPTION_EXECUTE_HANDLER) { 00332 00333 SepReleaseTokenWriteLock( Token, FALSE ); 00334 ObDereferenceObject( Token ); 00335 00336 if (CapturedPrivileges != NULL) { 00337 SeReleaseLuidAndAttributesArray( 00338 CapturedPrivileges, 00339 PreviousMode, 00340 TRUE 00341 ); 00342 } 00343 00344 return GetExceptionCode(); 00345 } 00346 00347 } 00348 00349 00350 // 00351 // Make sure there is enough room to return any requested 00352 // information. 00353 // 00354 00355 if (ARGUMENT_PRESENT(PreviousState)) { 00356 if (LocalReturnLength > BufferLength) { 00357 00358 SepReleaseTokenWriteLock( Token, FALSE ); 00359 ObDereferenceObject( Token ); 00360 00361 if (CapturedPrivileges != NULL) { 00362 SeReleaseLuidAndAttributesArray( 00363 CapturedPrivileges, 00364 PreviousMode, 00365 TRUE 00366 ); 00367 } 00368 00369 return STATUS_BUFFER_TOO_SMALL; 00370 } 00371 } 00372 00373 // 00374 // Second pass through the privileges list - Make the changes. 00375 // 00376 // Note that the internal routine attempts to write the previous 00377 // state directly to the caller's buffer - and so may get an exception. 00378 // 00379 00380 try { 00381 00382 Status = SepAdjustPrivileges( 00383 Token, 00384 TRUE, // Make the changes this pass 00385 DisableAllPrivileges, 00386 CapturedPrivilegeCount, 00387 CapturedPrivileges, 00388 PreviousState, 00389 &LocalReturnLength, 00390 &ChangeCount, 00391 &ChangesMade 00392 ); 00393 00394 00395 if (ARGUMENT_PRESENT(PreviousState)) { 00396 00397 PreviousState->PrivilegeCount = ChangeCount; 00398 } 00399 00400 } except(EXCEPTION_EXECUTE_HANDLER) { 00401 00402 SepReleaseTokenWriteLock( Token, TRUE ); 00403 ObDereferenceObject( Token ); 00404 if (CapturedPrivileges != NULL) { 00405 SeReleaseLuidAndAttributesArray( 00406 CapturedPrivileges, 00407 PreviousMode, 00408 TRUE 00409 ); 00410 } 00411 return GetExceptionCode(); 00412 00413 } 00414 00415 00416 SepReleaseTokenWriteLock( Token, ChangesMade ); 00417 ObDereferenceObject( Token ); 00418 if (CapturedPrivileges != NULL) { 00419 SeReleaseLuidAndAttributesArray( 00420 CapturedPrivileges, 00421 PreviousMode, 00422 TRUE 00423 ); 00424 } 00425 00426 return Status; 00427 00428 }

NTSTATUS SepAdjustGroups IN PTOKEN  Token,
IN BOOLEAN  MakeChanges,
IN BOOLEAN  ResetToDefault,
IN ULONG  GroupCount,
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 }


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