00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Semethod.c 00008 00009 Abstract: 00010 00011 This Module implements the SeDefaultObjectMethod procedure. This 00012 procedure and SeAssignSecurity are the only two procedures that will 00013 place a security descriptor on an object. Therefore they must understand 00014 and agree on how a descriptor is allocated from pool so that they can 00015 deallocate and reallocate pool as necessary. Any security descriptor 00016 that is attached to an object by these procedures has the following 00017 pool allocation plan. 00018 00019 1. if the objects security descriptor is null then there is no pool 00020 allocated 00021 00022 2. otherwise there is at least one pool allocation for the security 00023 descriptor header. if it's acl fields are null then there are no 00024 other pool allocations (this should never happen). 00025 00026 3. There is a separate pool allocation for each acl in the descriptor. 00027 So a maximum of three pool allocations can occur for each attached 00028 security descriptor. 00029 00030 4 Everytime an acl is replace in a descriptor we see if we can use 00031 the old acl and if so then we try and keep the acl size as large 00032 as possible. 00033 00034 Note that this is different from the algorithm used to capture 00035 a security descriptor (which puts everything in one pool allocation). 00036 Also note that this can be easily optimized at a later time (if necessary) 00037 to use only one allocation. 00038 00039 00040 00041 Author: 00042 00043 Gary Kimura (GaryKi) 9-Nov-1989 00044 Jim Kelly (JimK) 10-May-1990 00045 00046 Environment: 00047 00048 Kernel Mode 00049 00050 Revision History: 00051 00052 00053 --*/ 00054 00055 #include "sep.h" 00056 #include "sertlp.h" 00057 00058 NTSTATUS 00059 SepDefaultDeleteMethod ( 00060 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor 00061 ); 00062 00063 00064 00065 #ifdef ALLOC_PRAGMA 00066 #pragma alloc_text(PAGE,SeSetSecurityAccessMask) 00067 #pragma alloc_text(PAGE,SeQuerySecurityAccessMask) 00068 #pragma alloc_text(PAGE,SeDefaultObjectMethod) 00069 #pragma alloc_text(PAGE,SeSetSecurityDescriptorInfo) 00070 #pragma alloc_text(PAGE,SeQuerySecurityDescriptorInfo) 00071 #pragma alloc_text(PAGE,SepDefaultDeleteMethod) 00072 #endif 00073 00074 00075 00076 00077 VOID 00078 SeSetSecurityAccessMask( 00079 IN SECURITY_INFORMATION SecurityInformation, 00080 OUT PACCESS_MASK DesiredAccess 00081 ) 00082 00083 /*++ 00084 00085 Routine Description: 00086 00087 This routine builds an access mask representing the accesses necessary 00088 to set the object security information specified in the SecurityInformation 00089 parameter. While it is not difficult to determine this information, 00090 the use of a single routine to generate it will ensure minimal impact 00091 when the security information associated with an object is extended in 00092 the future (to include mandatory access control information). 00093 00094 Arguments: 00095 00096 SecurityInformation - Identifies the object's security information to be 00097 modified. 00098 00099 DesiredAccess - Points to an access mask to be set to represent the 00100 accesses necessary to modify the information specified in the 00101 SecurityInformation parameter. 00102 00103 Return Value: 00104 00105 None. 00106 00107 --*/ 00108 00109 { 00110 00111 PAGED_CODE(); 00112 00113 // 00114 // Figure out accesses needed to perform the indicated operation(s). 00115 // 00116 00117 (*DesiredAccess) = 0; 00118 00119 if ((SecurityInformation & OWNER_SECURITY_INFORMATION) || 00120 (SecurityInformation & GROUP_SECURITY_INFORMATION) ) { 00121 (*DesiredAccess) |= WRITE_OWNER; 00122 } 00123 00124 if (SecurityInformation & DACL_SECURITY_INFORMATION) { 00125 (*DesiredAccess) |= WRITE_DAC; 00126 } 00127 00128 if (SecurityInformation & SACL_SECURITY_INFORMATION) { 00129 (*DesiredAccess) |= ACCESS_SYSTEM_SECURITY; 00130 } 00131 00132 return; 00133 00134 } 00135 00136 00137 VOID 00138 SeQuerySecurityAccessMask( 00139 IN SECURITY_INFORMATION SecurityInformation, 00140 OUT PACCESS_MASK DesiredAccess 00141 ) 00142 00143 /*++ 00144 00145 Routine Description: 00146 00147 This routine builds an access mask representing the accesses necessary 00148 to query the object security information specified in the 00149 SecurityInformation parameter. While it is not difficult to determine 00150 this information, the use of a single routine to generate it will ensure 00151 minimal impact when the security information associated with an object is 00152 extended in the future (to include mandatory access control information). 00153 00154 Arguments: 00155 00156 SecurityInformation - Identifies the object's security information to be 00157 queried. 00158 00159 DesiredAccess - Points to an access mask to be set to represent the 00160 accesses necessary to query the information specified in the 00161 SecurityInformation parameter. 00162 00163 Return Value: 00164 00165 None. 00166 00167 --*/ 00168 00169 { 00170 PAGED_CODE(); 00171 00172 // 00173 // Figure out accesses needed to perform the indicated operation(s). 00174 // 00175 00176 (*DesiredAccess) = 0; 00177 00178 if ((SecurityInformation & OWNER_SECURITY_INFORMATION) || 00179 (SecurityInformation & GROUP_SECURITY_INFORMATION) || 00180 (SecurityInformation & DACL_SECURITY_INFORMATION)) { 00181 (*DesiredAccess) |= READ_CONTROL; 00182 } 00183 00184 if ((SecurityInformation & SACL_SECURITY_INFORMATION)) { 00185 (*DesiredAccess) |= ACCESS_SYSTEM_SECURITY; 00186 } 00187 00188 return; 00189 00190 } 00191 00192 00193 00194 NTSTATUS 00195 SeDefaultObjectMethod ( 00196 IN PVOID Object, 00197 IN SECURITY_OPERATION_CODE OperationCode, 00198 IN PSECURITY_INFORMATION SecurityInformation, 00199 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 00200 IN OUT PULONG CapturedLength, 00201 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 00202 IN POOL_TYPE PoolType, 00203 IN PGENERIC_MAPPING GenericMapping 00204 ) 00205 00206 /*++ 00207 00208 Routine Description: 00209 00210 This is the default security method for objects. It is responsible 00211 for either retrieving, setting, and deleting the security descriptor of 00212 an object. It is not used to assign the original security descriptor 00213 to an object (use SeAssignSecurity for that purpose). 00214 00215 00216 IT IS ASSUMED THAT THE OBJECT MANAGER HAS ALREADY DONE THE ACCESS 00217 VALIDATIONS NECESSARY TO ALLOW THE REQUESTED OPERATIONS TO BE PERFORMED. 00218 00219 Arguments: 00220 00221 Object - Supplies a pointer to the object being used. 00222 00223 OperationCode - Indicates if the operation is for setting, querying, or 00224 deleting the object's security descriptor. 00225 00226 SecurityInformation - Indicates which security information is being 00227 queried or set. This argument is ignored for the delete operation. 00228 00229 SecurityDescriptor - The meaning of this parameter depends on the 00230 OperationCode: 00231 00232 QuerySecurityDescriptor - For the query operation this supplies the 00233 buffer to copy the descriptor into. The security descriptor is 00234 assumed to have been probed up to the size passed in in Length. 00235 Since it still points into user space, it must always be 00236 accessed in a try clause in case it should suddenly disappear. 00237 00238 SetSecurityDescriptor - For a set operation this supplies the 00239 security descriptor to copy into the object. The security 00240 descriptor must be captured before this routine is called. 00241 00242 DeleteSecurityDescriptor - It is ignored when deleting a security 00243 descriptor. 00244 00245 AssignSecurityDescriptor - For assign operations this is the 00246 security descriptor that will be assigned to the object. 00247 It is assumed to be in kernel space, and is therefore not 00248 probed or captured. 00249 00250 CapturedLength - For the query operation this specifies the length, in 00251 bytes, of the security descriptor buffer, and upon return contains 00252 the number of bytes needed to store the descriptor. If the length 00253 needed is greater than the length supplied the operation will fail. 00254 It is ignored in the set and delete operation. 00255 00256 This parameter is assumed to be captured and probed as appropriate. 00257 00258 ObjectsSecurityDescriptor - For the Set operation this supplies the address 00259 of a pointer to the object's current security descriptor. This routine 00260 will either modify the security descriptor in place or allocate a new 00261 security descriptor and use this variable to indicate its new location. 00262 For the query operation it simply supplies the security descriptor 00263 being queried. The caller is responsible for freeing the old security 00264 descriptor. 00265 00266 PoolType - For the set operation this specifies the pool type to use if 00267 a new security descriptor needs to be allocated. It is ignored 00268 in the query and delete operation. 00269 00270 the mapping of generic to specific/standard access types for the object 00271 being accessed. This mapping structure is expected to be safe to 00272 access (i.e., captured if necessary) prior to be passed to this routine. 00273 00274 Return Value: 00275 00276 NTSTATUS - STATUS_SUCCESS if the operation is successful and an 00277 appropriate error status otherwise. 00278 00279 --*/ 00280 00281 { 00282 PAGED_CODE(); 00283 00284 // 00285 // If the object's security descriptor is null, then object is not 00286 // one that has security information associated with it. Return 00287 // an error. 00288 // 00289 00290 // 00291 // Make sure the common parts of our input are proper 00292 // 00293 00294 ASSERT( (OperationCode == SetSecurityDescriptor) || 00295 (OperationCode == QuerySecurityDescriptor) || 00296 (OperationCode == AssignSecurityDescriptor) || 00297 (OperationCode == DeleteSecurityDescriptor) ); 00298 00299 // 00300 // This routine simply cases off of the operation code to decide 00301 // which support routine to call 00302 // 00303 00304 switch (OperationCode) { 00305 00306 case SetSecurityDescriptor: 00307 00308 ASSERT( (PoolType == PagedPool) || (PoolType == NonPagedPool) ); 00309 00310 return ObSetSecurityDescriptorInfo( Object, 00311 SecurityInformation, 00312 SecurityDescriptor, 00313 ObjectsSecurityDescriptor, 00314 PoolType, 00315 GenericMapping 00316 ); 00317 00318 00319 00320 case QuerySecurityDescriptor: 00321 00322 // 00323 // check the rest of our input and call the default query security 00324 // method 00325 // 00326 00327 ASSERT( CapturedLength != NULL ); 00328 00329 return ObQuerySecurityDescriptorInfo( SecurityInformation, 00330 SecurityDescriptor, 00331 CapturedLength, 00332 ObjectsSecurityDescriptor ); 00333 00334 case DeleteSecurityDescriptor: 00335 00336 // 00337 // call the default delete security method 00338 // 00339 00340 return SepDefaultDeleteMethod( ObjectsSecurityDescriptor ); 00341 00342 case AssignSecurityDescriptor: 00343 00344 ObAssignObjectSecurityDescriptor( Object, SecurityDescriptor, PoolType ); 00345 return( STATUS_SUCCESS ); 00346 00347 default: 00348 00349 // 00350 // Bugcheck on any other operation code, We won't get here if 00351 // the earlier asserts are still checked. 00352 // 00353 00354 KeBugCheck( SECURITY_SYSTEM ); 00355 return( STATUS_INVALID_PARAMETER ); 00356 00357 } 00358 00359 } 00360 00361 00362 00363 00364 NTSTATUS 00365 SeSetSecurityDescriptorInfo ( 00366 IN PVOID Object OPTIONAL, 00367 IN PSECURITY_INFORMATION SecurityInformation, 00368 IN PSECURITY_DESCRIPTOR ModificationDescriptor, 00369 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 00370 IN POOL_TYPE PoolType, 00371 IN PGENERIC_MAPPING GenericMapping 00372 ) 00373 00374 /*++ 00375 00376 Routine Description: 00377 00378 This routine will set an object's security descriptor. The input 00379 security descriptor must be previously captured. 00380 00381 Arguments: 00382 00383 Object - Optionally supplies the object whose security is 00384 being adjusted. This is used to update security quota 00385 information. 00386 00387 SecurityInformation - Indicates which security information is 00388 to be applied to the object. The value(s) to be assigned are 00389 passed in the SecurityDescriptor parameter. 00390 00391 ModificationDescriptor - Supplies the input security descriptor to be 00392 applied to the object. The caller of this routine is expected 00393 to probe and capture the passed security descriptor before calling 00394 and release it after calling. 00395 00396 ObjectsSecurityDescriptor - Supplies the address of a pointer to 00397 the objects security descriptor that is going to be altered by 00398 this procedure. This structure must be deallocated by the caller. 00399 00400 PoolType - Specifies the type of pool to allocate for the objects 00401 security descriptor. 00402 00403 GenericMapping - This argument provides the mapping of generic to 00404 specific/standard access types for the object being accessed. 00405 This mapping structure is expected to be safe to access 00406 (i.e., captured if necessary) prior to be passed to this routine. 00407 00408 Return Value: 00409 00410 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error 00411 value otherwise. 00412 00413 --*/ 00414 00415 { 00416 00417 00418 00419 // 00420 // Make sure the object already has a security descriptor. 00421 // Objects that 'may' have security descriptors 'must' have security 00422 // descriptors. If this one doesn't already have one, then we can't 00423 // assign one to it. 00424 // 00425 00426 if ((*ObjectsSecurityDescriptor) == NULL) { 00427 return(STATUS_NO_SECURITY_ON_OBJECT); 00428 } 00429 00430 00431 // 00432 // Pass this call to the common Rtlp routine. 00433 // 00434 00435 return RtlpSetSecurityObject ( 00436 Object, 00437 *SecurityInformation, 00438 ModificationDescriptor, 00439 ObjectsSecurityDescriptor, 00440 0, // No Auto Inheritance 00441 PoolType, 00442 GenericMapping, 00443 NULL ); // No Token 00444 00445 00446 } 00447 00448 00449 00450 00451 NTSTATUS 00452 SeSetSecurityDescriptorInfoEx ( 00453 IN PVOID Object OPTIONAL, 00454 IN PSECURITY_INFORMATION SecurityInformation, 00455 IN PSECURITY_DESCRIPTOR ModificationDescriptor, 00456 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 00457 IN ULONG AutoInheritFlags, 00458 IN POOL_TYPE PoolType, 00459 IN PGENERIC_MAPPING GenericMapping 00460 ) 00461 00462 /*++ 00463 00464 Routine Description: 00465 00466 This routine will set an object's security descriptor. The input 00467 security descriptor must be previously captured. 00468 00469 Arguments: 00470 00471 Object - Optionally supplies the object whose security is 00472 being adjusted. This is used to update security quota 00473 information. 00474 00475 SecurityInformation - Indicates which security information is 00476 to be applied to the object. The value(s) to be assigned are 00477 passed in the SecurityDescriptor parameter. 00478 00479 ModificationDescriptor - Supplies the input security descriptor to be 00480 applied to the object. The caller of this routine is expected 00481 to probe and capture the passed security descriptor before calling 00482 and release it after calling. 00483 00484 ObjectsSecurityDescriptor - Supplies the address of a pointer to 00485 the objects security descriptor that is going to be altered by 00486 this procedure. This structure must be deallocated by the caller. 00487 00488 AutoInheritFlags - Controls automatic inheritance of ACES. 00489 Valid values are a bits mask of the logical OR of 00490 one or more of the following bits: 00491 00492 SEF_DACL_AUTO_INHERIT - If set, inherited ACEs from the 00493 DACL in the ObjectsSecurityDescriptor are preserved and inherited ACEs from 00494 the ModificationDescriptor are ignored. Inherited ACEs are not supposed 00495 to be modified; so preserving them across this call is appropriate. 00496 If a protected server does not itself implement auto inheritance, it should 00497 not set this bit. The caller of the protected server may implement 00498 auto inheritance and my indeed be modifying inherited ACEs. 00499 00500 SEF_SACL_AUTO_INHERIT - If set, inherited ACEs from the 00501 SACL in the ObjectsSecurityDescriptor are preserved and inherited ACEs from 00502 the ModificationDescriptor are ignored. Inherited ACEs are not supposed 00503 to be modified; so preserving them across this call is appropriate. 00504 If a protected server does not itself implement auto inheritance, it should 00505 not set this bit. The caller of the protected server may implement 00506 auto inheritance and my indeed be modifying inherited ACEs. 00507 00508 PoolType - Specifies the type of pool to allocate for the objects 00509 security descriptor. 00510 00511 GenericMapping - This argument provides the mapping of generic to 00512 specific/standard access types for the object being accessed. 00513 This mapping structure is expected to be safe to access 00514 (i.e., captured if necessary) prior to be passed to this routine. 00515 00516 Return Value: 00517 00518 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error 00519 value otherwise. 00520 00521 --*/ 00522 00523 { 00524 00525 00526 00527 // 00528 // Make sure the object already has a security descriptor. 00529 // Objects that 'may' have security descriptors 'must' have security 00530 // descriptors. If this one doesn't already have one, then we can't 00531 // assign one to it. 00532 // 00533 00534 if ((*ObjectsSecurityDescriptor) == NULL) { 00535 return(STATUS_NO_SECURITY_ON_OBJECT); 00536 } 00537 00538 00539 // 00540 // Pass this call to the common Rtlp routine. 00541 // 00542 00543 return RtlpSetSecurityObject ( 00544 Object, 00545 *SecurityInformation, 00546 ModificationDescriptor, 00547 ObjectsSecurityDescriptor, 00548 AutoInheritFlags, 00549 PoolType, 00550 GenericMapping, 00551 NULL ); // No Token 00552 00553 00554 } 00555 00556 00557 00558 NTSTATUS 00559 SeQuerySecurityDescriptorInfo ( 00560 IN PSECURITY_INFORMATION SecurityInformation, 00561 OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 00562 IN OUT PULONG Length, 00563 IN PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor 00564 ) 00565 00566 /*++ 00567 00568 Routine Description: 00569 00570 This routine will extract the desired information from the 00571 passed security descriptor and return the information in 00572 the passed buffer as a security descriptor in self-relative 00573 format. 00574 00575 Arguments: 00576 00577 SecurityInformation - Specifies what information is being queried. 00578 00579 SecurityDescriptor - Supplies the buffer to output the requested 00580 information into. 00581 00582 This buffer has been probed only to the size indicated by 00583 the Length parameter. Since it still points into user space, 00584 it must always be accessed in a try clause. 00585 00586 Length - Supplies the address of a variable containing the length of 00587 the security descriptor buffer. Upon return this variable will 00588 contain the length needed to store the requested information. 00589 00590 ObjectsSecurityDescriptor - Supplies the address of a pointer to 00591 the objects security descriptor. The passed security descriptor 00592 must be in self-relative format. 00593 00594 Return Value: 00595 00596 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error value 00597 otherwise 00598 00599 --*/ 00600 00601 { 00602 ULONG BufferLength; 00603 00604 ULONG Size; 00605 ULONG OwnerLength; 00606 ULONG GroupLength; 00607 ULONG DaclLength; 00608 ULONG SaclLength; 00609 PUCHAR NextFree; 00610 SECURITY_DESCRIPTOR IObjectSecurity; 00611 00612 // 00613 // Note that IObjectSecurity is not a pointer to a pointer 00614 // like ObjectsSecurityDescriptor is. 00615 // 00616 00617 SECURITY_DESCRIPTOR_RELATIVE *ISecurityDescriptor = SecurityDescriptor; 00618 00619 PAGED_CODE(); 00620 00621 // 00622 // We will be accessing user memory throughout this routine, 00623 // therefore do everything in a try-except clause. 00624 // 00625 00626 try { 00627 00628 BufferLength = *Length; 00629 00630 // 00631 // Check if the object's descriptor is null, and if it is then 00632 // we only need to return a blank security descriptor record 00633 // 00634 00635 if (*ObjectsSecurityDescriptor == NULL) { 00636 00637 *Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 00638 00639 // 00640 // Now make sure it's large enough for the security descriptor 00641 // record 00642 // 00643 00644 if (BufferLength < sizeof(SECURITY_DESCRIPTOR_RELATIVE)) { 00645 00646 return STATUS_BUFFER_TOO_SMALL; 00647 00648 } 00649 00650 // 00651 // It's large enough to make a blank security descriptor record 00652 // 00653 // Note that this parameter has been probed for write by the 00654 // object manager, however, we still have to be careful when 00655 // writing to it. 00656 // 00657 00658 // 00659 // We do not have to probe this here, because the object 00660 // manager has probed it for length=BufferLength, which we 00661 // know at this point is at least as large as a security 00662 // descriptor. 00663 // 00664 00665 RtlCreateSecurityDescriptorRelative( SecurityDescriptor, 00666 SECURITY_DESCRIPTOR_REVISION ); 00667 00668 // 00669 // Mark it as self-relative 00670 // 00671 00672 RtlpSetControlBits( ISecurityDescriptor, SE_SELF_RELATIVE ); 00673 00674 // 00675 // And return to our caller 00676 // 00677 00678 return STATUS_SUCCESS; 00679 00680 } 00681 00682 // 00683 // Create an absolute format SD on the stack pointing into 00684 // user space to simplify the following code 00685 // 00686 00687 RtlCopyMemory( (&IObjectSecurity), 00688 *ObjectsSecurityDescriptor, 00689 sizeof(SECURITY_DESCRIPTOR_RELATIVE) ); 00690 00691 IObjectSecurity.Owner = RtlpOwnerAddrSecurityDescriptor( 00692 (SECURITY_DESCRIPTOR *) *ObjectsSecurityDescriptor ); 00693 IObjectSecurity.Group = RtlpGroupAddrSecurityDescriptor( 00694 (SECURITY_DESCRIPTOR *) *ObjectsSecurityDescriptor ); 00695 IObjectSecurity.Dacl = RtlpDaclAddrSecurityDescriptor( 00696 (SECURITY_DESCRIPTOR *) *ObjectsSecurityDescriptor ); 00697 IObjectSecurity.Sacl = RtlpSaclAddrSecurityDescriptor( 00698 (SECURITY_DESCRIPTOR *) *ObjectsSecurityDescriptor ); 00699 00700 IObjectSecurity.Control &= ~SE_SELF_RELATIVE; 00701 00702 // 00703 // This is not a blank descriptor so we need to determine the size 00704 // needed to store the requested information. It is the size of the 00705 // descriptor record plus the size of each requested component. 00706 // 00707 00708 Size = sizeof(SECURITY_DESCRIPTOR_RELATIVE); 00709 00710 if ( (((*SecurityInformation) & OWNER_SECURITY_INFORMATION)) && 00711 (IObjectSecurity.Owner != NULL) ) { 00712 00713 OwnerLength = SeLengthSid( IObjectSecurity.Owner ); 00714 Size += (ULONG)LongAlignSize(OwnerLength); 00715 00716 } 00717 00718 if ( (((*SecurityInformation) & GROUP_SECURITY_INFORMATION)) && 00719 (IObjectSecurity.Group != NULL) ) { 00720 00721 GroupLength = SeLengthSid( IObjectSecurity.Group ); 00722 Size += (ULONG)LongAlignSize(GroupLength); 00723 00724 } 00725 00726 if ( (((*SecurityInformation) & DACL_SECURITY_INFORMATION)) && 00727 (IObjectSecurity.Control & SE_DACL_PRESENT) && 00728 (IObjectSecurity.Dacl != NULL) ) { 00729 00730 00731 DaclLength = (ULONG)LongAlignSize((IObjectSecurity.Dacl)->AclSize); 00732 Size += DaclLength; 00733 00734 } 00735 00736 if ( (((*SecurityInformation) & SACL_SECURITY_INFORMATION)) && 00737 (IObjectSecurity.Control & SE_SACL_PRESENT) && 00738 (IObjectSecurity.Sacl != NULL) ) { 00739 00740 SaclLength = (ULONG)LongAlignSize((IObjectSecurity.Sacl)->AclSize); 00741 Size += SaclLength; 00742 00743 } 00744 00745 // 00746 // Tell the caller how much space this will require 00747 // (whether we actually fit or not) 00748 // 00749 00750 *Length = Size; 00751 00752 // 00753 // Now make sure the size is less than or equal to the length 00754 // we were passed 00755 // 00756 00757 if (Size > BufferLength) { 00758 00759 return STATUS_BUFFER_TOO_SMALL; 00760 00761 } 00762 00763 // 00764 // The length is fine. 00765 // 00766 // Fill in the length and flags part of the security descriptor. 00767 // The real addresses of each acl will be filled in later when we 00768 // copy the ACLs over. 00769 // 00770 // Note that we only set a flag in the descriptor if the information 00771 // was requested, which is a simple copy of the requested information 00772 // input variable 00773 // 00774 // The output buffer has already been probed to the passed size, 00775 // so we can just write to it. 00776 // 00777 00778 RtlCreateSecurityDescriptorRelative( SecurityDescriptor, 00779 SECURITY_DESCRIPTOR_REVISION ); 00780 00781 // 00782 // Mark the returned Security Descriptor as being in 00783 // self-relative format 00784 // 00785 00786 RtlpSetControlBits( ISecurityDescriptor, SE_SELF_RELATIVE ); 00787 00788 // 00789 // NextFree is used to point to the next free spot in the 00790 // returned security descriptor. 00791 // 00792 00793 NextFree = LongAlignPtr((PUCHAR)SecurityDescriptor + 00794 sizeof(SECURITY_DESCRIPTOR_RELATIVE)); 00795 00796 // 00797 // Copy the Owner SID if necessary and update the NextFree pointer, 00798 // keeping it longword aligned. 00799 // 00800 00801 if ( ((*SecurityInformation) & OWNER_SECURITY_INFORMATION) && 00802 ((IObjectSecurity.Owner) != NULL) ) { 00803 00804 RtlMoveMemory( NextFree, 00805 IObjectSecurity.Owner, 00806 OwnerLength ); 00807 00808 ISecurityDescriptor->Owner = (ULONG)((PUCHAR)NextFree - (PUCHAR)SecurityDescriptor); 00809 00810 RtlpPropagateControlBits( 00811 ISecurityDescriptor, 00812 &IObjectSecurity, 00813 SE_OWNER_DEFAULTED 00814 ); 00815 00816 NextFree += (ULONG)LongAlignSize(OwnerLength); 00817 00818 } 00819 00820 00821 // 00822 // Copy the Group SID if necessary and update the NextFree pointer, 00823 // keeping it longword aligned. 00824 // 00825 00826 if ( ((*SecurityInformation) & GROUP_SECURITY_INFORMATION) && 00827 (IObjectSecurity.Group != NULL) ) { 00828 00829 RtlMoveMemory( NextFree, 00830 IObjectSecurity.Group, 00831 GroupLength ); 00832 00833 ISecurityDescriptor->Group = (ULONG)((PUCHAR)NextFree - (PUCHAR)SecurityDescriptor); 00834 00835 RtlpPropagateControlBits( 00836 ISecurityDescriptor, 00837 &IObjectSecurity, 00838 SE_GROUP_DEFAULTED 00839 ); 00840 00841 NextFree += (ULONG)LongAlignSize(GroupLength); 00842 00843 } 00844 00845 00846 // 00847 // Set discretionary acl information if requested. 00848 // If not set in object's security, 00849 // then everything is already set properly. 00850 // 00851 00852 if ( (*SecurityInformation) & DACL_SECURITY_INFORMATION) { 00853 00854 RtlpPropagateControlBits( 00855 ISecurityDescriptor, 00856 &IObjectSecurity, 00857 SE_DACL_PRESENT | SE_DACL_DEFAULTED | SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED 00858 ); 00859 00860 // 00861 // Copy the acl if non-null and update the NextFree pointer, 00862 // keeping it longword aligned. 00863 // 00864 00865 if ( (IObjectSecurity.Control & SE_DACL_PRESENT) != 0 && 00866 IObjectSecurity.Dacl != NULL) { 00867 00868 RtlMoveMemory( NextFree, 00869 IObjectSecurity.Dacl, 00870 (IObjectSecurity.Dacl)->AclSize ); 00871 00872 ISecurityDescriptor->Dacl = (ULONG)((PUCHAR)NextFree - (PUCHAR)SecurityDescriptor); 00873 00874 NextFree += DaclLength; 00875 00876 } 00877 } 00878 00879 00880 // 00881 // Set system acl information if requested. 00882 // If not set in object's security, 00883 // then everything is already set properly. 00884 // 00885 00886 if ( (*SecurityInformation) & SACL_SECURITY_INFORMATION) { 00887 00888 RtlpPropagateControlBits( 00889 ISecurityDescriptor, 00890 &IObjectSecurity, 00891 SE_SACL_PRESENT | SE_SACL_DEFAULTED | SE_SACL_PROTECTED | SE_SACL_AUTO_INHERITED 00892 ); 00893 00894 // 00895 // Copy the acl if non-null and update the NextFree pointer, 00896 // keeping it longword aligned. 00897 // 00898 if ( (IObjectSecurity.Control & SE_SACL_PRESENT) != 0 && 00899 IObjectSecurity.Sacl != NULL) { 00900 00901 RtlMoveMemory( NextFree, 00902 IObjectSecurity.Sacl, 00903 (IObjectSecurity.Sacl)->AclSize ); 00904 00905 ISecurityDescriptor->Sacl = (ULONG)((PUCHAR)NextFree - (PUCHAR)SecurityDescriptor); 00906 00907 } 00908 } 00909 00910 } except(EXCEPTION_EXECUTE_HANDLER) { 00911 return(GetExceptionCode()); 00912 } 00913 00914 return STATUS_SUCCESS; 00915 00916 } 00917 00918 00919 NTSTATUS 00920 SepDefaultDeleteMethod ( 00921 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor 00922 ) 00923 00924 /*++ 00925 00926 Routine Description: 00927 00928 This is a private procedure to delete the security descriptor for 00929 an object. It cleans up any pool allocations that have occured 00930 as part of the descriptor. 00931 00932 Arguments: 00933 00934 ObjectsSecurityDescriptor - Supplies the address of a pointer 00935 to the security descriptor being deleted. 00936 00937 Return Value: 00938 00939 NTSTATUS - STATUS_SUCCESS 00940 00941 --*/ 00942 00943 { 00944 PAGED_CODE(); 00945 00946 return (ObDeassignSecurity ( ObjectsSecurityDescriptor )); 00947 }