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

seastate.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Module Name: 00004 00005 SeAstate.c 00006 00007 Abstract: 00008 00009 This Module implements the privilege check procedures. 00010 00011 Author: 00012 00013 Robert Reichel (robertre) 20-March-90 00014 00015 Environment: 00016 00017 Kernel Mode 00018 00019 Revision History: 00020 00021 v1: robertre 00022 new file, move Access State related routines here 00023 00024 --*/ 00025 00026 #include "tokenp.h" 00027 00028 #ifdef ALLOC_PRAGMA 00029 #pragma alloc_text(PAGE,SeCreateAccessState) 00030 #pragma alloc_text(PAGE,SeDeleteAccessState) 00031 #pragma alloc_text(PAGE,SeAppendPrivileges) 00032 #pragma alloc_text(PAGE,SepConcatenatePrivileges) 00033 #endif 00034 00035 00036 // 00037 // Define logical sum of all generic accesses. 00038 // 00039 00040 #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL) 00041 00042 00043 // 00044 // The PRIVILEGE_SET data structure includes an array including ANYSIZE_ARRAY 00045 // elements. This definition provides the size of an empty PRIVILEGE_SET 00046 // (i.e., one with no privileges in it). 00047 // 00048 00049 #define SEP_PRIVILEGE_SET_HEADER_SIZE \ 00050 ((ULONG)sizeof(PRIVILEGE_SET) - \ 00051 (ANYSIZE_ARRAY * (ULONG)sizeof(LUID_AND_ATTRIBUTES))) 00052 00053 00054 00055 00056 00057 #if 0 00058 NTSTATUS 00059 SeCreateAccessState( 00060 IN PACCESS_STATE AccessState, 00061 IN ACCESS_MASK DesiredAccess, 00062 IN PGENERIC_MAPPING GenericMapping OPTIONAL 00063 ) 00064 00065 /*++ 00066 Routine Description: 00067 00068 This routine initializes an ACCESS_STATE structure. This consists 00069 of: 00070 00071 - zeroing the entire structure 00072 00073 - mapping generic access types in the passed DesiredAccess 00074 and putting it into the structure 00075 00076 - "capturing" the Subject Context, which must be held for the 00077 duration of the access attempt (at least until auditing is performed). 00078 00079 - Allocating an Operation ID, which is an LUID that will be used 00080 to associate different parts of the access attempt in the audit 00081 log. 00082 00083 Arguments: 00084 00085 AccessState - a pointer to the structure to be initialized. 00086 00087 DesiredAccess - Access mask containing the desired access 00088 00089 GenericMapping - Optionally supplies a pointer to a generic mapping 00090 that may be used to map any generic access requests that may 00091 have been passed in the DesiredAccess parameter. 00092 00093 Note that if this parameter is not supplied, it must be filled 00094 in at some later point. The IO system does this in IopParseDevice. 00095 00096 Return Value: 00097 00098 Error if the attempt to allocate an LUID fails. 00099 00100 Note that this error may be safely ignored if it is known that all 00101 security checks will be performed with PreviousMode == KernelMode. 00102 Know what you're doing if you choose to ignore this. 00103 00104 --*/ 00105 00106 { 00107 00108 ACCESS_MASK MappedAccessMask; 00109 PSECURITY_DESCRIPTOR InputSecurityDescriptor = NULL; 00110 PAUX_ACCESS_DATA AuxData; 00111 00112 PAGED_CODE(); 00113 00114 // 00115 // Don't modify what he passed in 00116 // 00117 00118 MappedAccessMask = DesiredAccess; 00119 00120 // 00121 // Map generic access to object specific access iff generic access types 00122 // are specified and a generic access mapping table is provided. 00123 // 00124 00125 if ( ((DesiredAccess & GENERIC_ACCESS) != 0) && 00126 ARGUMENT_PRESENT(GenericMapping) ) { 00127 00128 RtlMapGenericMask( 00129 &MappedAccessMask, 00130 GenericMapping 00131 ); 00132 } 00133 00134 RtlZeroMemory(AccessState, sizeof(ACCESS_STATE)); 00135 00136 // 00137 // Assume RtlZeroMemory has initialized these fields properly 00138 // 00139 00140 ASSERT( AccessState->SecurityDescriptor == NULL ); 00141 ASSERT( AccessState->PrivilegesAllocated == FALSE ); 00142 00143 AccessState->AuxData = ExAllocatePool( PagedPool, sizeof( AUX_ACCESS_DATA )); 00144 00145 if (AccessState->AuxData == NULL) { 00146 return( STATUS_NO_MEMORY ); 00147 } 00148 00149 AuxData = (PAUX_ACCESS_DATA)AccessState->AuxData; 00150 00151 SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); 00152 00153 if (((PTOKEN)EffectiveToken( &AccessState->SubjectSecurityContext ))->TokenFlags & TOKEN_HAS_TRAVERSE_PRIVILEGE ) { 00154 AccessState->Flags = TOKEN_HAS_TRAVERSE_PRIVILEGE; 00155 } 00156 00157 if (SeTokenIsRestricted(EffectiveToken( &AccessState-SubjectSecurityContext))) { 00158 AccessState->Flags |= TOKEN_IS_RESTRICTED; 00159 } 00160 00161 AccessState->RemainingDesiredAccess = MappedAccessMask; 00162 AccessState->OriginalDesiredAccess = DesiredAccess; 00163 AuxData->PrivilegesUsed = (PPRIVILEGE_SET)((PUCHAR)AccessState + 00164 (FIELD_OFFSET(ACCESS_STATE, Privileges))); 00165 00166 ExAllocateLocallyUniqueId(&AccessState->OperationID); 00167 00168 if (ARGUMENT_PRESENT(GenericMapping)) { 00169 AuxData->GenericMapping = *GenericMapping; 00170 } 00171 00172 return( STATUS_SUCCESS ); 00173 00174 } 00175 00176 #endif 00177 00178 00179 NTSTATUS 00180 SeCreateAccessState( 00181 IN PACCESS_STATE AccessState, 00182 IN PAUX_ACCESS_DATA AuxData, 00183 IN ACCESS_MASK DesiredAccess, 00184 IN PGENERIC_MAPPING GenericMapping OPTIONAL 00185 ) 00186 00187 /*++ 00188 Routine Description: 00189 00190 This routine initializes an ACCESS_STATE structure. This consists 00191 of: 00192 00193 - zeroing the entire structure 00194 00195 - mapping generic access types in the passed DesiredAccess 00196 and putting it into the structure 00197 00198 - "capturing" the Subject Context, which must be held for the 00199 duration of the access attempt (at least until auditing is performed). 00200 00201 - Allocating an Operation ID, which is an LUID that will be used 00202 to associate different parts of the access attempt in the audit 00203 log. 00204 00205 Arguments: 00206 00207 AccessState - a pointer to the structure to be initialized. 00208 00209 AuxData - Supplies a buffer big enough for an AuxData structure 00210 so we don't have to allocate one. 00211 00212 DesiredAccess - Access mask containing the desired access 00213 00214 GenericMapping - Optionally supplies a pointer to a generic mapping 00215 that may be used to map any generic access requests that may 00216 have been passed in the DesiredAccess parameter. 00217 00218 Note that if this parameter is not supplied, it must be filled 00219 in at some later point. The IO system does this in IopParseDevice. 00220 00221 Return Value: 00222 00223 Error if the attempt to allocate an LUID fails. 00224 00225 Note that this error may be safely ignored if it is known that all 00226 security checks will be performed with PreviousMode == KernelMode. 00227 Know what you're doing if you choose to ignore this. 00228 00229 --*/ 00230 00231 { 00232 00233 ACCESS_MASK MappedAccessMask; 00234 PSECURITY_DESCRIPTOR InputSecurityDescriptor = NULL; 00235 00236 PAGED_CODE(); 00237 00238 // 00239 // Don't modify what he passed in 00240 // 00241 00242 MappedAccessMask = DesiredAccess; 00243 00244 // 00245 // Map generic access to object specific access iff generic access types 00246 // are specified and a generic access mapping table is provided. 00247 // 00248 00249 if ( ((DesiredAccess & GENERIC_ACCESS) != 0) && 00250 ARGUMENT_PRESENT(GenericMapping) ) { 00251 00252 RtlMapGenericMask( 00253 &MappedAccessMask, 00254 GenericMapping 00255 ); 00256 } 00257 00258 RtlZeroMemory(AccessState, sizeof(ACCESS_STATE)); 00259 00260 // 00261 // Assume RtlZeroMemory has initialized these fields properly 00262 // 00263 00264 ASSERT( AccessState->SecurityDescriptor == NULL ); 00265 ASSERT( AccessState->PrivilegesAllocated == FALSE ); 00266 00267 AccessState->AuxData = AuxData; 00268 00269 SeCaptureSubjectContext(&AccessState->SubjectSecurityContext); 00270 00271 if (((PTOKEN)EffectiveToken( &AccessState->SubjectSecurityContext ))->TokenFlags & TOKEN_HAS_TRAVERSE_PRIVILEGE ) { 00272 AccessState->Flags = TOKEN_HAS_TRAVERSE_PRIVILEGE; 00273 } 00274 00275 AccessState->RemainingDesiredAccess = MappedAccessMask; 00276 AccessState->OriginalDesiredAccess = MappedAccessMask; 00277 AuxData->PrivilegesUsed = (PPRIVILEGE_SET)((ULONG_PTR)AccessState + 00278 (FIELD_OFFSET(ACCESS_STATE, Privileges))); 00279 00280 ExAllocateLocallyUniqueId(&AccessState->OperationID); 00281 00282 if (ARGUMENT_PRESENT(GenericMapping)) { 00283 AuxData->GenericMapping = *GenericMapping; 00284 } 00285 00286 return( STATUS_SUCCESS ); 00287 00288 } 00289 00290 00291 #if 0 00292 00293 00294 VOID 00295 SeDeleteAccessState( 00296 PACCESS_STATE AccessState 00297 ) 00298 00299 /*++ 00300 00301 Routine Description: 00302 00303 This routine deallocates any memory that may have been allocated as 00304 part of constructing the access state (normally only for an excessive 00305 number of privileges), and frees the Subject Context. 00306 00307 Arguments: 00308 00309 AccessState - a pointer to the ACCESS_STATE structure to be 00310 deallocated. 00311 00312 Return Value: 00313 00314 None. 00315 00316 --*/ 00317 00318 { 00319 PAUX_ACCESS_DATA AuxData; 00320 00321 PAGED_CODE(); 00322 00323 AuxData = (PAUX_ACCESS_DATA)AccessState->AuxData; 00324 00325 if (AccessState->PrivilegesAllocated) { 00326 ExFreePool( (PVOID)AuxData->PrivilegesUsed ); 00327 } 00328 00329 if (AccessState->ObjectName.Buffer != NULL) { 00330 ExFreePool(AccessState->ObjectName.Buffer); 00331 } 00332 00333 if (AccessState->ObjectTypeName.Buffer != NULL) { 00334 ExFreePool(AccessState->ObjectTypeName.Buffer); 00335 } 00336 00337 ExFreePool( AuxData ); 00338 00339 SeReleaseSubjectContext(&AccessState->SubjectSecurityContext); 00340 00341 return; 00342 } 00343 00344 00345 #endif 00346 00347 VOID 00348 SeDeleteAccessState( 00349 PACCESS_STATE AccessState 00350 ) 00351 00352 /*++ 00353 00354 Routine Description: 00355 00356 This routine deallocates any memory that may have been allocated as 00357 part of constructing the access state (normally only for an excessive 00358 number of privileges), and frees the Subject Context. 00359 00360 Arguments: 00361 00362 AccessState - a pointer to the ACCESS_STATE structure to be 00363 deallocated. 00364 00365 Return Value: 00366 00367 None. 00368 00369 --*/ 00370 00371 { 00372 PAUX_ACCESS_DATA AuxData; 00373 00374 PAGED_CODE(); 00375 00376 AuxData = (PAUX_ACCESS_DATA)AccessState->AuxData; 00377 00378 if (AccessState->PrivilegesAllocated) { 00379 ExFreePool( (PVOID)AuxData->PrivilegesUsed ); 00380 } 00381 00382 if (AccessState->ObjectName.Buffer != NULL) { 00383 ExFreePool(AccessState->ObjectName.Buffer); 00384 } 00385 00386 if (AccessState->ObjectTypeName.Buffer != NULL) { 00387 ExFreePool(AccessState->ObjectTypeName.Buffer); 00388 } 00389 00390 SeReleaseSubjectContext(&AccessState->SubjectSecurityContext); 00391 00392 return; 00393 } 00394 00395 VOID 00396 SeSetAccessStateGenericMapping ( 00397 PACCESS_STATE AccessState, 00398 PGENERIC_MAPPING GenericMapping 00399 ) 00400 00401 /*++ 00402 00403 Routine Description: 00404 00405 This routine sets the GenericMapping field in an AccessState structure. 00406 It must be called before access validation is performed if the GenericMapping 00407 is not passed in when the AccessState structure is created. 00408 00409 Arguments: 00410 00411 AccessState - a pointer to the ACCESS_STATE structure to be modified. 00412 00413 GenericMapping - a pointer to the GenericMapping to be copied into the AccessState. 00414 00415 Return Value: 00416 00417 00418 --*/ 00419 { 00420 PAUX_ACCESS_DATA AuxData; 00421 00422 PAGED_CODE(); 00423 00424 AuxData = (PAUX_ACCESS_DATA)AccessState->AuxData; 00425 00426 AuxData->GenericMapping = *GenericMapping; 00427 00428 return; 00429 } 00430 00431 00432 00433 NTSTATUS 00434 SeAppendPrivileges( 00435 PACCESS_STATE AccessState, 00436 PPRIVILEGE_SET Privileges 00437 ) 00438 /*++ 00439 00440 Routine Description: 00441 00442 This routine takes a privilege set and adds it to the privilege set 00443 imbedded in an ACCESS_STATE structure. 00444 00445 An AccessState may contain up to three imbedded privileges. To 00446 add more, this routine will allocate a block of memory, copy 00447 the current privileges into it, and append the new privilege 00448 to that block. A bit is set in the AccessState indicating that 00449 the pointer to the privilge set in the structure points to pool 00450 memory and must be deallocated. 00451 00452 Arguments: 00453 00454 AccessState - The AccessState structure representing the current 00455 access attempt. 00456 00457 Privileges - A pointer to a privilege set to be added. 00458 00459 Return Value: 00460 00461 STATUS_INSUFFICIENT_RESOURCES - an attempt to allocate pool memory 00462 failed. 00463 00464 --*/ 00465 00466 { 00467 ULONG NewPrivilegeSetSize; 00468 PPRIVILEGE_SET NewPrivilegeSet; 00469 PAUX_ACCESS_DATA AuxData; 00470 00471 PAGED_CODE(); 00472 00473 AuxData = (PAUX_ACCESS_DATA)AccessState->AuxData; 00474 00475 if (Privileges->PrivilegeCount + AuxData->PrivilegesUsed->PrivilegeCount > 00476 INITIAL_PRIVILEGE_COUNT) { 00477 00478 // 00479 // Compute the total size of the two privilege sets 00480 // 00481 00482 NewPrivilegeSetSize = SepPrivilegeSetSize( Privileges ) + 00483 SepPrivilegeSetSize( AuxData->PrivilegesUsed ); 00484 00485 NewPrivilegeSet = ExAllocatePoolWithTag( PagedPool, NewPrivilegeSetSize, 'rPeS' ); 00486 00487 if (NewPrivilegeSet == NULL) { 00488 return( STATUS_INSUFFICIENT_RESOURCES ); 00489 } 00490 00491 00492 RtlCopyMemory( 00493 NewPrivilegeSet, 00494 AuxData->PrivilegesUsed, 00495 SepPrivilegeSetSize( AuxData->PrivilegesUsed ) 00496 ); 00497 00498 // 00499 // Note that this will adjust the privilege count in the 00500 // structure for us. 00501 // 00502 00503 SepConcatenatePrivileges( 00504 NewPrivilegeSet, 00505 NewPrivilegeSetSize, 00506 Privileges 00507 ); 00508 00509 if (AccessState->PrivilegesAllocated) { 00510 ExFreePool( AuxData->PrivilegesUsed ); 00511 } 00512 00513 AuxData->PrivilegesUsed = NewPrivilegeSet; 00514 00515 // 00516 // Mark that we've allocated memory for the privilege set, 00517 // so we know to free it when we're cleaning up. 00518 // 00519 00520 AccessState->PrivilegesAllocated = TRUE; 00521 00522 } else { 00523 00524 // 00525 // Note that this will adjust the privilege count in the 00526 // structure for us. 00527 // 00528 00529 SepConcatenatePrivileges( 00530 AuxData->PrivilegesUsed, 00531 sizeof(INITIAL_PRIVILEGE_SET), 00532 Privileges 00533 ); 00534 00535 } 00536 00537 return( STATUS_SUCCESS ); 00538 00539 } 00540 00541 00542 VOID 00543 SepConcatenatePrivileges( 00544 IN PPRIVILEGE_SET TargetPrivilegeSet, 00545 IN ULONG TargetBufferSize, 00546 IN PPRIVILEGE_SET SourcePrivilegeSet 00547 ) 00548 00549 /*++ 00550 00551 Routine Description: 00552 00553 Takes two privilege sets and appends the second to the end of the 00554 first. 00555 00556 There must be enough space left at the end of the first privilege 00557 set to contain the second. 00558 00559 Arguments: 00560 00561 TargetPrivilegeSet - Supplies a buffer containing a privilege set. 00562 The buffer must be large enough to contain the second privilege 00563 set. 00564 00565 TargetBufferSize - Supplies the size of the target buffer. 00566 00567 SourcePrivilegeSet - Supplies the privilege set to be copied 00568 into the target buffer. 00569 00570 Return Value: 00571 00572 None 00573 00574 --*/ 00575 00576 { 00577 PVOID Base; 00578 PVOID Source; 00579 ULONG Length; 00580 00581 PAGED_CODE(); 00582 00583 ASSERT( ((ULONG)SepPrivilegeSetSize( TargetPrivilegeSet ) + 00584 (ULONG)SepPrivilegeSetSize( SourcePrivilegeSet ) - 00585 SEP_PRIVILEGE_SET_HEADER_SIZE ) <= 00586 TargetBufferSize 00587 ); 00588 00589 Base = (PVOID)((ULONG_PTR)TargetPrivilegeSet + SepPrivilegeSetSize( TargetPrivilegeSet )); 00590 00591 Source = (PVOID) ((ULONG_PTR)SourcePrivilegeSet + SEP_PRIVILEGE_SET_HEADER_SIZE); 00592 00593 Length = SourcePrivilegeSet->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES); 00594 00595 RtlMoveMemory( 00596 Base, 00597 Source, 00598 Length 00599 ); 00600 00601 TargetPrivilegeSet->PrivilegeCount += SourcePrivilegeSet->PrivilegeCount; 00602 00603 }

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