test: seurtl.c Source File

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

# seurtl.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     seurtl.c
    00008
    00009 Abstract:
    00010
    00011     This Module implements many security rtl routines defined in nturtl.h
    00012
    00013 Author:
    00014
    00015     Robert Reichel  (RobertRe)  1-Mar-1991
    00016
    00017 Environment:
    00018
    00019     Pure Runtime Library Routine
    00020     User mode callable only
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026
    00027 #include <ntos.h>
    00028 #include <nturtl.h>
    00029 #include <ntlsa.h>      // needed for RtlGetPrimaryDomain
    00030 #include "seopaque.h"
    00031 #include "sertlp.h"
    00032 #include "ldrp.h"
    00033
    00034
    00035
    00036
    00037
    00039 //                                                                           //
    00040 //    Exported Procedures                                                    //
    00041 //                                                                           //
    00043
    00044
    00045 #if WHEN_LSAUDLL_MOVED_TO_NTDLL
    00046 NTSTATUS
    00047 RtlGetPrimaryDomain(
    00048     IN  ULONG            SidLength,
    00049     OUT PBOOLEAN         PrimaryDomainPresent,
    00050     OUT PUNICODE_STRING  PrimaryDomainName,
    00051     OUT PUSHORT          RequiredNameLength,
    00052     OUT PSID             PrimaryDomainSid OPTIONAL,
    00053     OUT PULONG           RequiredSidLength
    00054     )
    00055
    00056 /*++
    00057
    00058 Routine Description:
    00059
    00060     This procedure opens the LSA policy object and retrieves
    00061     the primary domain information for this machine.
    00062
    00063 Arguments:
    00064
    00065     SidLength - Specifies the length of the PrimaryDomainSid
    00066         parameter.
    00067
    00068     PrimaryDomainPresent - Receives a boolean value indicating
    00069         whether this machine has a primary domain or not. TRUE
    00070         indicates the machine does have a primary domain. FALSE
    00071         indicates the machine does not.
    00072
    00073     PrimaryDomainName - Points to the unicode string to receive
    00074         the primary domain name.  This parameter will only be
    00075         used if there is a primary domain.
    00076
    00077     RequiredNameLength - Recevies the length of the primary
    00078         domain name (in bytes).  This parameter will only be
    00079         used if there is a primary domain.
    00080
    00081     PrimaryDomainSid - This optional parameter, if present,
    00082         points to a buffer to receive the primary domain's
    00083         SID.  This parameter will only be used if there is a
    00084         primary domain.
    00085
    00086     RequiredSidLength - Recevies the length of the primary
    00087         domain SID (in bytes).  This parameter will only be
    00088         used if there is a primary domain.
    00089
    00090
    00091 Return Value:
    00092
    00093     STATUS_SUCCESS - The requested information has been retrieved.
    00094
    00095     STATUS_BUFFER_TOO_SMALL - One of the return buffers was not
    00096         large enough to receive the corresponding information.
    00097         The RequiredNameLength and RequiredSidLength parameter
    00098         values have been set to indicate the needed length.
    00099
    00100     Other status values as may be returned by:
    00101
    00102         LsaOpenPolicy()
    00103         LsaQueryInformationPolicy()
    00104         RtlCopySid()
    00105
    00106
    00107 --*/
    00108
    00109
    00110
    00111
    00112 {
    00113     NTSTATUS Status, IgnoreStatus;
    00114     OBJECT_ATTRIBUTES ObjectAttributes;
    00115     LSA_HANDLE LsaHandle;
    00116     SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
    00117     PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo;
    00118
    00119
    00120     //
    00121     // Set up the Security Quality Of Service
    00122     //
    00123
    00124     SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
    00125     SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
    00126     SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    00127     SecurityQualityOfService.EffectiveOnly = FALSE;
    00128
    00129     //
    00130     // Set up the object attributes to open the Lsa policy object
    00131     //
    00132
    00133     InitializeObjectAttributes(&ObjectAttributes,
    00134                                NULL,
    00135                                0L,
    00136                                (HANDLE)NULL,
    00137                                NULL);
    00138     ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
    00139
    00140     //
    00141     // Open the local LSA policy object
    00142     //
    00143
    00144     Status = LsaOpenPolicy( NULL,
    00145                             &ObjectAttributes,
    00146                             POLICY_VIEW_LOCAL_INFORMATION,
    00147                             &LsaHandle
    00148                           );
    00149     if (NT_SUCCESS(Status)) {
    00150
    00151         //
    00152         // Get the primary domain info
    00153         //
    00154         Status = LsaQueryInformationPolicy(LsaHandle,
    00155                                            PolicyPrimaryDomainInformation,
    00156                                            (PVOID *)&PrimaryDomainInfo);
    00157         IgnoreStatus = LsaClose(LsaHandle);
    00158         ASSERT(NT_SUCCESS(IgnoreStatus));
    00159     }
    00160
    00161     if (NT_SUCCESS(Status)) {
    00162
    00163         //
    00164         // Is there a primary domain?
    00165         //
    00166
    00167         if (PrimaryDomainInfo->Sid != NULL) {
    00168
    00169             //
    00170             // Yes
    00171             //
    00172
    00173             (*PrimaryDomainPresent) = TRUE;
    00174             (*RequiredNameLength) = PrimaryDomainInfo->Name.Length;
    00175             (*RequiredSidLength)  = RtlLengthSid(PrimaryDomainInfo->Sid);
    00176
    00177
    00178
    00179             //
    00180             // Copy the name
    00181             //
    00182
    00183             if (PrimaryDomainName->MaximumLength >=
    00184                 PrimaryDomainInfo->Name.Length) {
    00185                 RtlCopyUnicodeString(
    00186                     PrimaryDomainName,
    00187                     &PrimaryDomainInfo->Name
    00188                     );
    00189             } else {
    00190                 Status = STATUS_BUFFER_TOO_SMALL;
    00191             }
    00192
    00193
    00194             //
    00195             // Copy the SID (if appropriate)
    00196             //
    00197
    00198             if (PrimaryDomainSid != NULL && NT_SUCCESS(Status)) {
    00199
    00200                 Status = RtlCopySid(SidLength,
    00201                                     PrimaryDomainSid,
    00202                                     PrimaryDomainInfo->Sid
    00203                                     );
    00204             }
    00205         } else {
    00206
    00207             (*PrimaryDomainPresent) = FALSE;
    00208         }
    00209
    00210         //
    00211         // We're finished with the buffer returned by LSA
    00212         //
    00213
    00214         IgnoreStatus = LsaFreeMemory(PrimaryDomainInfo);
    00215         ASSERT(NT_SUCCESS(IgnoreStatus));
    00216
    00217     }
    00218
    00219
    00220     return(Status);
    00221 }
    00222 #endif //WHEN_LSAUDLL_MOVED_TO_NTDLL
    00223
    00224
    00225 NTSTATUS
    00226 RtlNewSecurityObjectEx (
    00227     IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
    00228     IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
    00229     OUT PSECURITY_DESCRIPTOR * NewDescriptor,
    00230     IN GUID *ObjectType OPTIONAL,
    00231     IN BOOLEAN IsDirectoryObject,
    00232     IN ULONG AutoInheritFlags,
    00233     IN HANDLE Token OPTIONAL,
    00234     IN PGENERIC_MAPPING GenericMapping
    00235     )
    00236 /*++
    00237
    00238 Routine Description:
    00239
    00240     See RtlpNewSecurityObject.
    00241
    00242                               - - WARNING - -
    00243
    00244     This service is for use by protected subsystems that project their own
    00245     type of object.  This service is explicitly not for use by the
    00246     executive for executive objects and must not be called from kernel
    00247     mode.
    00248
    00249 Arguments:
    00250
    00251     See RtlpNewSecurityObject.
    00252
    00253 Return Value:
    00254
    00255     See RtlpNewSecurityObject.
    00256
    00257 --*/
    00258 {
    00259
    00260     //
    00261     // Simple call the newer RtlpNewSecurityObject
    00262     //
    00263
    00264     return RtlpNewSecurityObject (
    00265                 ParentDescriptor,
    00266                 CreatorDescriptor,
    00267                 NewDescriptor,
    00268                 ObjectType,
    00269                 IsDirectoryObject,
    00270                 AutoInheritFlags,
    00271                 Token,
    00272                 GenericMapping );
    00273
    00274 }
    00275
    00276
    00277
    00278
    00279 NTSTATUS
    00280 RtlNewSecurityObject (
    00281     IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
    00282     IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
    00283     OUT PSECURITY_DESCRIPTOR * NewDescriptor,
    00284     IN BOOLEAN IsDirectoryObject,
    00285     IN HANDLE Token,
    00286     IN PGENERIC_MAPPING GenericMapping
    00287     )
    00288 /*++
    00289
    00290 Routine Description:
    00291
    00292     See RtlpNewSecurityObject.
    00293
    00294                               - - WARNING - -
    00295
    00296     This service is for use by protected subsystems that project their own
    00297     type of object.  This service is explicitly not for use by the
    00298     executive for executive objects and must not be called from kernel
    00299     mode.
    00300
    00301 Arguments:
    00302
    00303     See RtlpNewSecurityObject.
    00304
    00305 Return Value:
    00306
    00307     See RtlpNewSecurityObject.
    00308
    00309 --*/
    00310 {
    00311
    00312     //
    00313     // Simple call the newer RtlpNewSecurityObject
    00314     //
    00315
    00316     return RtlpNewSecurityObject (
    00317                 ParentDescriptor,
    00318                 CreatorDescriptor,
    00319                 NewDescriptor,
    00320                 NULL,   // No ObjectType
    00321                 IsDirectoryObject,
    00322                 0,      // No Automatic inheritance
    00323                 Token,
    00324                 GenericMapping );
    00325
    00326 }
    00327
    00328
    00329
    00330 NTSTATUS
    00331 RtlSetSecurityObject (
    00332     IN SECURITY_INFORMATION SecurityInformation,
    00333     IN PSECURITY_DESCRIPTOR ModificationDescriptor,
    00334     IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    00335     IN PGENERIC_MAPPING GenericMapping,
    00336     IN HANDLE Token OPTIONAL
    00337     )
    00338 /*++
    00339
    00340 Routine Description:
    00341
    00342     See RtlpSetSecurityObject.
    00343
    00344 Arguments:
    00345
    00346     See RtlpSetSecurityObject.
    00347
    00348 Return Value:
    00349
    00350     See RtlpSetSecurityObject.
    00351
    00352 --*/
    00353
    00354 {
    00355
    00356     //
    00357     // Simply call RtlpSetSecurityObject specifying no auto inheritance.
    00358     //
    00359
    00360     return RtlpSetSecurityObject( NULL,
    00361                                   SecurityInformation,
    00362                                   ModificationDescriptor,
    00363                                   ObjectsSecurityDescriptor,
    00364                                   0,   // No AutoInheritance
    00365                                   PagedPool,
    00366                                   GenericMapping,
    00367                                   Token );
    00368 }
    00369
    00370
    00371
    00372 NTSTATUS
    00373 RtlSetSecurityObjectEx (
    00374     IN SECURITY_INFORMATION SecurityInformation,
    00375     IN PSECURITY_DESCRIPTOR ModificationDescriptor,
    00376     IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
    00377     IN ULONG AutoInheritFlags,
    00378     IN PGENERIC_MAPPING GenericMapping,
    00379     IN HANDLE Token OPTIONAL
    00380     )
    00381 /*++
    00382
    00383 Routine Description:
    00384
    00385     See RtlpSetSecurityObject.
    00386
    00387 Arguments:
    00388
    00389     See RtlpSetSecurityObject.
    00390
    00391 Return Value:
    00392
    00393     See RtlpSetSecurityObject.
    00394
    00395 --*/
    00396
    00397 {
    00398
    00399     //
    00400     // Simply call RtlpSetSecurityObject specifying no auto inheritance.
    00401     //
    00402
    00403     return RtlpSetSecurityObject( NULL,
    00404                                   SecurityInformation,
    00405                                   ModificationDescriptor,
    00406                                   ObjectsSecurityDescriptor,
    00407                                   AutoInheritFlags,
    00408                                   PagedPool,
    00409                                   GenericMapping,
    00410                                   Token );
    00411 }
    00412
    00413
    00414
    00415
    00416
    00417 NTSTATUS
    00418 RtlQuerySecurityObject (
    00419     IN PSECURITY_DESCRIPTOR ObjectDescriptor,
    00420     IN SECURITY_INFORMATION SecurityInformation,
    00421     OUT PSECURITY_DESCRIPTOR ResultantDescriptor,
    00422     IN ULONG DescriptorLength,
    00423     OUT PULONG ReturnLength
    00424     )
    00425
    00426 /*++
    00427
    00428 Routine Description:
    00429
    00430     Query information from a protected server object's existing security
    00431     descriptor.
    00432
    00433     This procedure, called only from user mode, is used to retrieve
    00434     information from a security descriptor on an existing protected
    00435     server's object.  All access checking is expected to be done before
    00436     calling this routine.  This includes checking for READ_CONTROL, and
    00437     privilege to read a system ACL as appropriate.
    00438
    00439                           - - WARNING - -
    00440
    00441     This service is for use by protected subsystems that project their own
    00442     type of object.  This service is explicitly not for use by the
    00443     executive for executive objects and must not be called from kernel
    00444     mode.
    00445
    00446
    00447 Arguments:
    00448
    00449     ObjectDescriptor - Points to a pointer to a security descriptor to be
    00450         queried.
    00451
    00452     SecurityInformation - Identifies the security information being
    00453         requested.
    00454
    00455     ResultantDescriptor - Points to buffer to receive the resultant
    00456         security descriptor.  The resultant security descriptor will
    00457         contain all information requested by the SecurityInformation
    00458         parameter.
    00459
    00460     DescriptorLength - Is an unsigned integer which indicates the length,
    00461         in bytes, of the buffer provided to receive the resultant
    00462         descriptor.
    00463
    00464     ReturnLength - Receives an unsigned integer indicating the actual
    00465         number of bytes needed in the ResultantDescriptor to store the
    00466         requested information.  If the value returned is greater than the
    00467         value passed via the DescriptorLength parameter, then
    00468         STATUS_BUFFER_TOO_SMALL is returned and no information is returned.
    00469
    00470
    00471 Return Value:
    00472
    00473     STATUS_SUCCESS - The operation was successful.
    00474
    00475     STATUS_BUFFER_TOO_SMALL - The buffer provided to receive the requested
    00476         information was not large enough to hold the information.  No
    00477         information has been returned.
    00478
    00479     STATUS_BAD_DESCRIPTOR_FORMAT - Indicates the provided object's security
    00480         descriptor was not in self-relative format.
    00481
    00482 --*/
    00483
    00484 {
    00485
    00486     PSID Group;
    00487     PSID Owner;
    00488     PACL Dacl;
    00489     PACL Sacl;
    00490
    00491     ULONG GroupSize = 0;
    00492     ULONG DaclSize = 0;
    00493     ULONG SaclSize = 0;
    00494     ULONG OwnerSize = 0;
    00495
    00496     PCHAR Field;
    00497     PCHAR Base;
    00498
    00499
    00500     PISECURITY_DESCRIPTOR IObjectDescriptor;
    00501     PISECURITY_DESCRIPTOR_RELATIVE IResultantDescriptor;
    00502
    00503
    00504     IResultantDescriptor = (PISECURITY_DESCRIPTOR_RELATIVE)ResultantDescriptor;
    00505     IObjectDescriptor = (PISECURITY_DESCRIPTOR)ObjectDescriptor;
    00506
    00507     //
    00508     // For each item specified in the SecurityInformation, extract it
    00509     // and get it to the point where it can be copied into a new
    00510     // descriptor.
    00511     //
    00512
    00513     if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
    00514
    00515         Group = RtlpGroupAddrSecurityDescriptor(IObjectDescriptor);
    00516         GroupSize = LongAlignSize(SeLengthSid(Group));
    00517     }
    00518
    00519     if (SecurityInformation & DACL_SECURITY_INFORMATION) {
    00520
    00521         Dacl = RtlpDaclAddrSecurityDescriptor( IObjectDescriptor );
    00522
    00523         if (Dacl != NULL) {
    00524             DaclSize = LongAlignSize(Dacl->AclSize);
    00525         }
    00526     }
    00527
    00528     if (SecurityInformation & SACL_SECURITY_INFORMATION) {
    00529
    00530         Sacl = RtlpSaclAddrSecurityDescriptor( IObjectDescriptor );
    00531
    00532         if (Sacl != NULL) {
    00533             SaclSize = LongAlignSize(Sacl->AclSize);
    00534         }
    00535
    00536     }
    00537
    00538     if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
    00539
    00540         Owner = RtlpOwnerAddrSecurityDescriptor ( IObjectDescriptor );
    00541         OwnerSize = LongAlignSize(SeLengthSid(Owner));
    00542     }
    00543
    00544     *ReturnLength = sizeof( SECURITY_DESCRIPTOR_RELATIVE ) +
    00545                     GroupSize +
    00546                     DaclSize  +
    00547                     SaclSize  +
    00548                     OwnerSize;
    00549
    00550     if (*ReturnLength > DescriptorLength) {
    00551         return( STATUS_BUFFER_TOO_SMALL );
    00552     }
    00553
    00554     RtlCreateSecurityDescriptor(
    00555         IResultantDescriptor,
    00556         SECURITY_DESCRIPTOR_REVISION
    00557         );
    00558
    00559     RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE );
    00560
    00561     Base = (PCHAR)(IResultantDescriptor);
    00562     Field =  Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
    00563
    00564     if (SecurityInformation & SACL_SECURITY_INFORMATION) {
    00565
    00566         if (SaclSize > 0) {
    00567             RtlMoveMemory( Field, Sacl, SaclSize );
    00568             IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field);
    00569             Field += SaclSize;
    00570         }
    00571
    00572         RtlpPropagateControlBits(
    00573             IResultantDescriptor,
    00574             IObjectDescriptor,
    00575             SE_SACL_PRESENT | SE_SACL_DEFAULTED
    00576             );
    00577     }
    00578
    00579     if (SecurityInformation & DACL_SECURITY_INFORMATION) {
    00580
    00581         if (DaclSize > 0) {
    00582             RtlMoveMemory( Field, Dacl, DaclSize );
    00583             IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field);
    00584             Field += DaclSize;
    00585         }
    00586
    00587         RtlpPropagateControlBits(
    00588             IResultantDescriptor,
    00589             IObjectDescriptor,
    00590             SE_DACL_PRESENT | SE_DACL_DEFAULTED
    00591             );
    00592     }
    00593
    00594     if (SecurityInformation & OWNER_SECURITY_INFORMATION) {
    00595
    00596         if (OwnerSize > 0) {
    00597             RtlMoveMemory( Field, Owner, OwnerSize );
    00598             IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field);
    00599             Field += OwnerSize;
    00600         }
    00601
    00602         RtlpPropagateControlBits(
    00603             IResultantDescriptor,
    00604             IObjectDescriptor,
    00605             SE_OWNER_DEFAULTED
    00606             );
    00607
    00608     }
    00609
    00610     if (SecurityInformation & GROUP_SECURITY_INFORMATION) {
    00611
    00612         if (GroupSize > 0) {
    00613             RtlMoveMemory( Field, Group, GroupSize );
    00614             IResultantDescriptor->Group = RtlPointerToOffset(Base,Field);
    00615         }
    00616
    00617         RtlpPropagateControlBits(
    00618             IResultantDescriptor,
    00619             IObjectDescriptor,
    00620             SE_GROUP_DEFAULTED
    00621             );
    00622     }
    00623
    00624     return( STATUS_SUCCESS );
    00625
    00626 }
    00627
    00628
    00629
    00630
    00631
    00632 NTSTATUS
    00633 RtlDeleteSecurityObject (
    00634     IN OUT PSECURITY_DESCRIPTOR * ObjectDescriptor
    00635     )
    00636
    00637
    00638 /*++
    00639
    00640 Routine Description:
    00641
    00642     Delete a protected server object's security descriptor.
    00643
    00644     This procedure, called only from user mode, is used to delete a
    00645     security descriptor associated with a protected server's object.  This
    00646     routine will normally be called by a protected server during object
    00647     deletion.
    00648
    00649                                   - - WARNING - -
    00650
    00651     This service is for use by protected subsystems that project their own
    00652     type of object.  This service is explicitly not for use by the
    00653     executive for executive objects and must not be called from kernel
    00654     mode.
    00655
    00656
    00657 Arguments:
    00658
    00659     ObjectDescriptor - Points to a pointer to a security descriptor to be
    00660         deleted.
    00661
    00662
    00663 Return Value:
    00664
    00665     STATUS_SUCCESS - The operation was successful.
    00666
    00667 --*/
    00668
    00669 {
    00670     RtlFreeHeap( RtlProcessHeap(), 0, (PVOID)*ObjectDescriptor );
    00671
    00672     return( STATUS_SUCCESS );
    00673
    00674 }
    00675
    00676
    00677
    00678
    00679 NTSTATUS
    00680 RtlNewInstanceSecurityObject(
    00681     IN BOOLEAN ParentDescriptorChanged,
    00682     IN BOOLEAN CreatorDescriptorChanged,
    00683     IN PLUID OldClientTokenModifiedId,
    00684     OUT PLUID NewClientTokenModifiedId,
    00685     IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
    00686     IN PSECURITY_DESCRIPTOR CreatorDescriptor OPTIONAL,
    00687     OUT PSECURITY_DESCRIPTOR * NewDescriptor,
    00688     IN BOOLEAN IsDirectoryObject,
    00689     IN HANDLE Token,
    00690     IN PGENERIC_MAPPING GenericMapping
    00691     )
    00692
    00693 /*++
    00694
    00695 Routine Description:
    00696
    00697     If the return status is STATUS_SUCCESS and the NewSecurity return
    00698     value is NULL, then the security desscriptor of the original
    00699     instance of the object is valid for this instance as well.
    00700
    00701 Arguments:
    00702
    00703     ParentDescriptorChanged - Supplies a flag indicating whether the
    00704         parent security descriptor has changed since the last time
    00705         this set of parameters was used.
    00706
    00707     CreatorDescriptorChanged - Supplies a flag indicating whether the
    00708         creator security descriptor has changed since the last time
    00709         this set of parameters was used.
    00710
    00711     OldClientTokenModifiedId - Supplies the ModifiedId from the passed
    00712         token that was in effect when this call was last made with
    00713         these parameters.  If the current ModifiedId is different from
    00714         the one passed in here, the security descriptor must be
    00715         rebuilt.
    00716
    00717     NewClientTokenModifiedId - Returns the current ModifiedId from the
    00718         passed token.
    00719
    00720     ParentDescriptor - Supplies the Security Descriptor for the parent
    00721         directory under which a new object is being created.  If there is
    00722         no parent directory, then this argument is specified as NULL.
    00723
    00724     CreatorDescriptor - (Optionally) Points to a security descriptor
    00725         presented by the creator of the object.  If the creator of the
    00726         object did not explicitly pass security information for the new
    00727         object, then a null pointer should be passed.
    00728
    00729     NewDescriptor - Points to a pointer that is to be made to point to the
    00730         newly allocated self-relative security descriptor.
    00731
    00732     IsDirectoryObject - Specifies if the new object is going to be a
    00733         directory object.  A value of TRUE indicates the object is a
    00734         container of other objects.
    00735
    00736     Token - Supplies the token for the client on whose behalf the
    00737         object is being created.  If it is an impersonation token,
    00738         then it must be at SecurityIdentification level or higher.  If
    00739         it is not an impersonation token, the operation proceeds
    00740         normally.
    00741
    00742         A client token is used to retrieve default security
    00743         information for the new object, such as default owner, primary
    00744         group, and discretionary access control.  The token must be
    00745         open for TOKEN_QUERY access.
    00746
    00747     GenericMapping - Supplies a pointer to a generic mapping array denoting
    00748         the mapping between each generic right to specific rights.
    00749
    00750 Return Value:
    00751
    00752     return-value - Description of conditions needed to return value. - or -
    00753     None.
    00754
    00755 --*/
    00756
    00757 {
    00758
    00759     TOKEN_STATISTICS ClientTokenStatistics;
    00760     ULONG ReturnLength;
    00761     NTSTATUS Status;
    00762
    00763
    00764
    00765     //
    00766     // Get the current token modified LUID
    00767     //
    00768
    00769
    00770     Status = NtQueryInformationToken(
    00771                  Token,                        // Handle
    00772                  TokenStatistics,              // TokenInformationClass
    00773                  &ClientTokenStatistics,       // TokenInformation
    00774                  sizeof(TOKEN_STATISTICS),     // TokenInformationLength
    00775                  &ReturnLength                 // ReturnLength
    00776                  );
    00777
    00778     if ( !NT_SUCCESS( Status )) {
    00779         return( Status );
    00780     }
    00781
    00782     *NewClientTokenModifiedId = ClientTokenStatistics.ModifiedId;
    00783
    00784     if ( RtlEqualLuid(NewClientTokenModifiedId, OldClientTokenModifiedId) ) {
    00785
    00786         if ( !(ParentDescriptorChanged || CreatorDescriptorChanged) ) {
    00787
    00788             //
    00789             // The old security descriptor is valid for this new instance
    00790             // of the object type as well.  Pass back success and NULL for
    00791             // the NewDescriptor.
    00792             //
    00793
    00794             *NewDescriptor = NULL;
    00795             return( STATUS_SUCCESS );
    00796
    00797         }
    00798     }
    00799
    00800     //
    00801     // Something has changed, take the long route and build a new
    00802     // descriptor
    00803     //
    00804
    00805     return( RtlNewSecurityObject( ParentDescriptor,
    00806                                   CreatorDescriptor,
    00807                                   NewDescriptor,
    00808                                   IsDirectoryObject,
    00809                                   Token,
    00810                                   GenericMapping
    00811                                   ));
    00812 }
    00813
    00814
    00815
    00816
    00817 NTSTATUS
    00818 RtlNewSecurityGrantedAccess(
    00819     IN ACCESS_MASK DesiredAccess,
    00820     OUT PPRIVILEGE_SET Privileges,
    00821     IN OUT PULONG Length,
    00822     IN HANDLE Token OPTIONAL,
    00823     IN PGENERIC_MAPPING GenericMapping,
    00824     OUT PACCESS_MASK RemainingDesiredAccess
    00825     )
    00826
    00827 /*++
    00828
    00829 Routine Description:
    00830
    00831     This routine implements privilege policy by examining the bits in
    00832     a DesiredAccess mask and adjusting them based on privilege checks.
    00833
    00834     Currently, a request for ACCESS_SYSTEM_SECURITY may only be satisfied
    00835     by the caller having SeSecurityPrivilege.
    00836
    00837     Note that this routine is only to be called when an object is being
    00838     created.  When an object is being opened, it is expected that
    00839     NtAccessCheck will be called, and that routine will implement
    00840     another policy for substituting privileges for DACL access.
    00841
    00842 Arguments:
    00843
    00844     DesiredAccess - Supplies the user's desired access mask
    00845
    00846     Privileges - Supplies a pointer to an empty buffer in which will
    00847         be returned a privilege set describing any privileges that were
    00848         used to gain access.
    00849
    00850         Note that this is not an optional parameter, that is, enough
    00851         room for a single privilege must always be passed.
    00852
    00853     Length - Supplies the length of the Privileges parameter in bytes.
    00854         If the supplies length is not adequate to store the entire
    00855         privilege set, this field will return the minimum length required.
    00856
    00857     Token - (optionally) Supplies the token for the client on whose
    00858         behalf the object is being accessed.  If this value is
    00859         specified as null, then the token on the thread is opened and
    00860         examined to see if it is an impersonation token.  If it is,
    00861         then it must be at SecurityIdentification level or higher.  If
    00862         it is not an impersonation token, the operation proceeds
    00863         normally.
    00864
    00865     GenericMapping - Supplies the generic mapping associated with this
    00866         object type.
    00867
    00868     RemainingDesiredAccess - Returns the DesiredAccess mask after any bits
    00869         have been masked off.  If no access types could be granted, this
    00870         mask will be identical to the one passed in.
    00871
    00872 Return Value:
    00873
    00874     STATUS_SUCCESS - The operation completed successfully.
    00875
    00876     STATUS_BUFFER_TOO_SMALL - The passed buffer was not large enough
    00877         to contain the information being returned.
    00878
    00879     STATUS_BAD_IMPERSONATION_LEVEL - The caller or passed token was
    00880         impersonating, but not at a high enough level.
    00881
    00882
    00883 --*/
    00884
    00885 {
    00886     PRIVILEGE_SET RequiredPrivilege;
    00887     BOOLEAN Result = FALSE;
    00888     NTSTATUS Status;
    00889     ULONG PrivilegeCount = 0;
    00890     HANDLE ThreadToken;
    00891     BOOLEAN TokenPassed;
    00892     TOKEN_STATISTICS ThreadTokenStatistics;
    00893     ULONG ReturnLength;
    00894     ULONG SizeRequired;
    00895     ULONG PrivilegeNumber = 0;
    00896
    00897
    00898     //
    00899     //  If the caller hasn't passed a token, call the kernel and get
    00900     //  his impersonation token.  This call will fail if the caller is
    00901     //  not impersonating a client, so if the caller is not
    00902     //  impersonating someone, he'd better have passed in an explicit
    00903     //  token.
    00904     //
    00905
    00906     if (!ARGUMENT_PRESENT( Token )) {
    00907
    00908         Status = NtOpenThreadToken(
    00909                      NtCurrentThread(),
    00910                      TOKEN_QUERY,
    00911                      TRUE,
    00912                      &ThreadToken
    00913                      );
    00914
    00915         TokenPassed = FALSE;
    00916
    00917         if (!NT_SUCCESS( Status )) {
    00918             return( Status );
    00919         }
    00920
    00921     } else {
    00922
    00923         ThreadToken = Token;
    00924         TokenPassed = TRUE;
    00925     }
    00926
    00927     Status = NtQueryInformationToken(
    00928                  ThreadToken,                  // Handle
    00929                  TokenStatistics,              // TokenInformationClass
    00930                  &ThreadTokenStatistics,       // TokenInformation
    00931                  sizeof(TOKEN_STATISTICS),     // TokenInformationLength
    00932                  &ReturnLength                 // ReturnLength
    00933                  );
    00934
    00935     ASSERT( NT_SUCCESS(Status) );
    00936
    00937     RtlMapGenericMask(
    00938         &DesiredAccess,
    00939         GenericMapping
    00940         );
    00941
    00942     *RemainingDesiredAccess = DesiredAccess;
    00943
    00944     if ( DesiredAccess & ACCESS_SYSTEM_SECURITY ) {
    00945
    00946         RequiredPrivilege.PrivilegeCount = 1;
    00947         RequiredPrivilege.Control = PRIVILEGE_SET_ALL_NECESSARY;
    00948         RequiredPrivilege.Privilege[0].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
    00949         RequiredPrivilege.Privilege[0].Attributes = 0;
    00950
    00951         //
    00952         // NtPrivilegeCheck will make sure we are impersonating
    00953         // properly.
    00954         //
    00955
    00956         Status = NtPrivilegeCheck(
    00957                      ThreadToken,
    00958                      &RequiredPrivilege,
    00959                      &Result
    00960                      );
    00961
    00962         if ( (!NT_SUCCESS ( Status )) || (!Result) ) {
    00963
    00964             if (!TokenPassed) {
    00965                 NtClose( ThreadToken );
    00966             }
    00967
    00968             if ( !NT_SUCCESS( Status )) {
    00969                 return( Status );
    00970             }
    00971
    00972             if ( !Result ) {
    00973                 return( STATUS_PRIVILEGE_NOT_HELD );
    00974             }
    00975
    00976         }
    00977
    00978         //
    00979         // We have the required privilege, turn off the bit in
    00980         // copy of the input mask and remember that we need to return
    00981         // this privilege.
    00982         //
    00983
    00984         *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
    00985     }
    00986
    00987     if (!TokenPassed) {
    00988         NtClose( ThreadToken );
    00989     }
    00990
    00991     SizeRequired = sizeof(PRIVILEGE_SET);
    00992
    00993     if ( SizeRequired > *Length ) {
    00994         *Length = SizeRequired;
    00995         return( STATUS_BUFFER_TOO_SMALL );
    00996     }
    00997
    00998     if (Result) {
    00999
    01000         Privileges->PrivilegeCount = 1;
    01001         Privileges->Control = 0;
    01002         Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
    01003         Privileges->Privilege[PrivilegeNumber].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
    01004
    01005     } else {
    01006
    01007         Privileges->PrivilegeCount = 0;
    01008         Privileges->Control = 0;
    01009         Privileges->Privilege[PrivilegeNumber].Luid = RtlConvertLongToLuid(0);
    01010         Privileges->Privilege[PrivilegeNumber].Attributes = 0;
    01011
    01012     }
    01013
    01014     return( STATUS_SUCCESS );
    01015
    01016 }
    01017
    01018
    01019
    01020 NTSTATUS
    01021 RtlCopySecurityDescriptor(
    01022     IN PSECURITY_DESCRIPTOR InputSecurityDescriptor,
    01023     OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor
    01024     )
    01025
    01026 /*++
    01027
    01028 Routine Description:
    01029
    01030     This routine will copy a self-relative security descriptor from
    01031     any memory into the correct type of memory required by security
    01032     descriptor Rtl routines.
    01033
    01034     This allows security descriptors to be kept in whatever kind of
    01035     storage is most convenient for the current application.  A security
    01036     descriptor should be copied via this routine and the copy passed
    01037     into any Rtl routine that in any way modify the security descriptor
    01038     (eg RtlSetSecurityObject).
    01039
    01040     The storage allocated by this routine must be freed by
    01041     RtlDeleteSecurityObject.
    01042
    01043 Arguments:
    01044
    01045     InputSecurityDescriptor - contains the source security descriptor
    01046
    01047     OutputSecurityDescriptor - returns a copy of the security descriptor
    01048         in the correct kind of memory.
    01049
    01050
    01051 Return Value:
    01052
    01053     STATUS_NO_MEMORY - There was not enough memory available to the current
    01054         process to complete this operation.
    01055
    01056 --*/
    01057
    01058 {
    01059
    01060     PACL Dacl;
    01061     PACL Sacl;
    01062
    01063     PSID Owner;
    01064     PSID PrimaryGroup;
    01065
    01066     ULONG DaclSize;
    01067     ULONG OwnerSize;
    01068     ULONG PrimaryGroupSize;
    01069     ULONG SaclSize;
    01070     ULONG TotalSize;
    01071
    01072     PISECURITY_DESCRIPTOR ISecurityDescriptor =
    01073                             (PISECURITY_DESCRIPTOR)InputSecurityDescriptor;
    01074
    01075
    01076     RtlpQuerySecurityDescriptor(
    01077         ISecurityDescriptor,
    01078         &Owner,
    01079         &OwnerSize,
    01080         &PrimaryGroup,
    01081         &PrimaryGroupSize,
    01082         &Dacl,
    01083         &DaclSize,
    01084         &Sacl,
    01085         &SaclSize
    01086         );
    01087
    01088     TotalSize = sizeof(SECURITY_DESCRIPTOR) +
    01089                 OwnerSize +
    01090                 PrimaryGroupSize +
    01091                 DaclSize +
    01092                 SaclSize;
    01093
    01094     *OutputSecurityDescriptor = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG( SE_TAG ), TotalSize );
    01095
    01096     if ( *OutputSecurityDescriptor == NULL ) {
    01097         return( STATUS_NO_MEMORY );
    01098     }
    01099
    01100     RtlMoveMemory( *OutputSecurityDescriptor,
    01101                    ISecurityDescriptor,
    01102                    TotalSize
    01103                    );
    01104
    01105     return( STATUS_SUCCESS );
    01106
    01107 }
    01108
    01109
    01110 NTSTATUS
    01111 RtlpInitializeAllowedAce(
    01112     IN  PACCESS_ALLOWED_ACE AllowedAce,
    01113     IN  USHORT AceSize,
    01114     IN  UCHAR InheritFlags,
    01115     IN  UCHAR AceFlags,
    01116     IN  ACCESS_MASK Mask,
    01117     IN  PSID AllowedSid
    01118     )
    01119 /*++
    01120
    01121 Routine Description:
    01122
    01123     This function assigns the specified ACE values into an allowed type ACE.
    01124
    01125 Arguments:
    01126
    01127     AllowedAce - Supplies a pointer to the ACE that is initialized.
    01128
    01129     AceSize - Supplies the size of the ACE in bytes.
    01130
    01131     InheritFlags - Supplies ACE inherit flags.
    01132
    01133     AceFlags - Supplies ACE type specific control flags.
    01134
    01135     Mask - Supplies the allowed access masks.
    01136
    01137     AllowedSid - Supplies the pointer to the SID of user/group which is allowed
    01138         the specified access.
    01139
    01140 Return Value:
    01141
    01142     Returns status from RtlCopySid.
    01143
    01144 --*/
    01145 {
    01146     AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    01147     AllowedAce->Header.AceSize = AceSize;
    01148     AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
    01149
    01150     AllowedAce->Mask = Mask;
    01151
    01152     return RtlCopySid(
    01153                RtlLengthSid(AllowedSid),
    01154                &(AllowedAce->SidStart),
    01155                AllowedSid
    01156                );
    01157 }
    01158
    01159
    01160 NTSTATUS
    01161 RtlpInitializeDeniedAce(
    01162     IN  PACCESS_DENIED_ACE DeniedAce,
    01163     IN  USHORT AceSize,
    01164     IN  UCHAR InheritFlags,
    01165     IN  UCHAR AceFlags,
    01166     IN  ACCESS_MASK Mask,
    01167     IN  PSID DeniedSid
    01168     )
    01169 /*++
    01170
    01171 Routine Description:
    01172
    01173     This function assigns the specified ACE values into a denied type ACE.
    01174
    01175 Arguments:
    01176
    01177     DeniedAce - Supplies a pointer to the ACE that is initialized.
    01178
    01179     AceSize - Supplies the size of the ACE in bytes.
    01180
    01181     InheritFlags - Supplies ACE inherit flags.
    01182
    01183     AceFlags - Supplies ACE type specific control flags.
    01184
    01185     Mask - Supplies the denied access masks.
    01186
    01187     AllowedSid - Supplies the pointer to the SID of user/group which is denied
    01188         the specified access.
    01189
    01190 Return Value:
    01191
    01192     Returns status from RtlCopySid.
    01193
    01194 --*/
    01195 {
    01196     DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
    01197     DeniedAce->Header.AceSize = AceSize;
    01198     DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
    01199
    01200     DeniedAce->Mask = Mask;
    01201
    01202     return RtlCopySid(
    01203                RtlLengthSid(DeniedSid),
    01204                &(DeniedAce->SidStart),
    01205                DeniedSid
    01206                );
    01207 }
    01208
    01209
    01210 NTSTATUS
    01211 RtlpInitializeAuditAce(
    01212     IN  PACCESS_ALLOWED_ACE AuditAce,
    01213     IN  USHORT AceSize,
    01214     IN  UCHAR InheritFlags,
    01215     IN  UCHAR AceFlags,
    01216     IN  ACCESS_MASK Mask,
    01217     IN  PSID AuditSid
    01218     )
    01219 /*++
    01220
    01221 Routine Description:
    01222
    01223     This function assigns the specified ACE values into an audit type ACE.
    01224
    01225 Arguments:
    01226
    01227     AuditAce - Supplies a pointer to the ACE that is initialized.
    01228
    01229     AceSize - Supplies the size of the ACE in bytes.
    01230
    01231     InheritFlags - Supplies ACE inherit flags.
    01232
    01233     AceFlags - Supplies ACE type specific control flags.
    01234
    01235     Mask - Supplies the allowed access masks.
    01236
    01237     AuditSid - Supplies the pointer to the SID of user/group which is to be
    01238         audited.
    01239
    01240 Return Value:
    01241
    01242     Returns status from RtlCopySid.
    01243
    01244 --*/
    01245 {
    01246     AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
    01247     AuditAce->Header.AceSize = AceSize;
    01248     AuditAce->Header.AceFlags = AceFlags | InheritFlags;
    01249
    01250     AuditAce->Mask = Mask;
    01251
    01252     return RtlCopySid(
    01253                RtlLengthSid(AuditSid),
    01254                &(AuditAce->SidStart),
    01255                AuditSid
    01256                );
    01257 }
    01258
    01259 NTSTATUS
    01260 RtlCreateAndSetSD(
    01261     IN  PRTL_ACE_DATA AceData,
    01262     IN  ULONG AceCount,
    01263     IN  PSID OwnerSid OPTIONAL,
    01264     IN  PSID GroupSid OPTIONAL,
    01265     OUT PSECURITY_DESCRIPTOR *NewDescriptor
    01266     )
    01267 /*++
    01268
    01269 Routine Description:
    01270
    01271     This function creates an absolute security descriptor containing
    01272     the supplied ACE information.
    01273
    01274     A sample usage of this function:
    01275
    01276         //
    01277         // Order matters!  These ACEs are inserted into the DACL in the
    01278         // following order.  Security access is granted or denied based on
    01279         // the order of the ACEs in the DACL.
    01280         //
    01281
    01282         RTL_ACE_DATA AceData[4] = {
    01283             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01284                    GENERIC_ALL,                  &LocalAdminSid},
    01285
    01286             {ACCESS_DENIED_ACE_TYPE,  0, 0,
    01287                    GENERIC_ALL,                  &NetworkSid},
    01288
    01289             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01290                    WKSTA_CONFIG_GUEST_INFO_GET |
    01291                    WKSTA_CONFIG_USER_INFO_GET,   &DomainUsersSid},
    01292
    01293             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01294                    WKSTA_CONFIG_GUEST_INFO_GET,  &DomainGuestsSid}
    01295             };
    01296
    01297         PSECURITY_DESCRIPTOR WkstaSecurityDescriptor;
    01298
    01299
    01300         return RtlCreateAndSetSD(
    01301                    AceData,
    01302                    4,
    01303                    LocalSystemSid,
    01304                    LocalSystemSid,
    01305                    &WkstaSecurityDescriptor
    01306                    );
    01307
    01308 Arguments:
    01309
    01310     AceData - Supplies the structure of information that describes the DACL.
    01311
    01312     AceCount - Supplies the number of entries in AceData structure.
    01313
    01314     OwnerSid - Supplies the pointer to the SID of the security descriptor
    01315         owner.  If not specified, a security descriptor with no owner
    01316         will be created.
    01317
    01318     GroupSid - Supplies the pointer to the SID of the security descriptor
    01319         primary group.  If not specified, a security descriptor with no primary
    01320         group will be created.
    01321
    01322     NewDescriptor - Returns a pointer to the absolute security descriptor
    01323         allocated using RtlAllocateHeap.
    01324
    01325 Return Value:
    01326
    01327     STATUS_SUCCESS - if successful
    01328     STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
    01329         security descriptor.
    01330
    01331     Any other status codes returned from the security Rtl routines.
    01332
    01333     NOTE : the user security object created by calling this function may be
    01334                 freed up by calling RtlDeleteSecurityObject().
    01335
    01336 --*/
    01337 {
    01338
    01339     NTSTATUS ntstatus = STATUS_SUCCESS;
    01340     ULONG i;
    01341
    01342     //
    01343     // Pointer to memory dynamically allocated by this routine to hold
    01344     // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
    01345     //
    01346     // +---------------------------------------------------------------+
    01347     // |                     Security Descriptor                       |
    01348     // +-------------------------------+-------+---------------+-------+
    01349     // |          DACL                 | ACE 1 |   .  .  .     | ACE n |
    01350     // +-------------------------------+-------+---------------+-------+
    01351     // |          SACL                 | ACE 1 |   .  .  .     | ACE n |
    01352     // +-------------------------------+-------+---------------+-------+
    01353     //
    01354
    01355     PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
    01356     PACL Dacl = NULL;   // Pointer to the DACL portion of above buffer
    01357     PACL Sacl = NULL;   // Pointer to the SACL portion of above buffer
    01358
    01359     ULONG DaclSize = sizeof(ACL);
    01360     ULONG SaclSize = sizeof(ACL);
    01361     ULONG MaxAceSize = 0;
    01362     PVOID MaxAce = NULL;
    01363
    01364     PCHAR CurrentAvailable;
    01365     ULONG Size;
    01366
    01367     PVOID HeapHandle = RtlProcessHeap();
    01368
    01369
    01370     ASSERT( AceCount > 0 );
    01371
    01372     //
    01373     // Compute the total size of the DACL and SACL ACEs and the maximum
    01374     // size of any ACE.
    01375     //
    01376
    01377     for (i = 0; i < AceCount; i++) {
    01378         ULONG AceSize;
    01379
    01380         AceSize = RtlLengthSid(*(AceData[i].Sid));
    01381
    01382         switch (AceData[i].AceType) {
    01383         case ACCESS_ALLOWED_ACE_TYPE:
    01384             AceSize += sizeof(ACCESS_ALLOWED_ACE);
    01385             DaclSize += AceSize;
    01386             break;
    01387
    01388         case ACCESS_DENIED_ACE_TYPE:
    01389             AceSize += sizeof(ACCESS_DENIED_ACE);
    01390             DaclSize += AceSize;
    01391             break;
    01392
    01393         case SYSTEM_AUDIT_ACE_TYPE:
    01394             AceSize += sizeof(SYSTEM_AUDIT_ACE);
    01395             SaclSize += AceSize;
    01396             break;
    01397
    01398         default:
    01399             return STATUS_INVALID_PARAMETER;
    01400         }
    01401
    01402         MaxAceSize = MaxAceSize > AceSize ? MaxAceSize : AceSize;
    01403     }
    01404
    01405     //
    01406     // Allocate a chunk of memory large enough for the security descriptor,
    01407     // the DACL, the SACL and all ACEs.
    01408     //
    01409     // A security descriptor is of opaque data type but
    01410     // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
    01411     //
    01412
    01413     Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
    01414     if ( DaclSize != sizeof(ACL) ) {
    01415         Size += DaclSize;
    01416     }
    01417     if ( SaclSize != sizeof(ACL) ) {
    01418         Size += SaclSize;
    01419     }
    01420
    01421     if ((AbsoluteSd = RtlAllocateHeap(
    01422                           HeapHandle, MAKE_TAG( SE_TAG ),
    01423                           Size
    01424                           )) == NULL) {
    01425         ntstatus = STATUS_NO_MEMORY;
    01426         goto Cleanup;
    01427     }
    01428
    01429     //
    01430     // Initialize the Dacl and Sacl
    01431     //
    01432
    01433     CurrentAvailable = (PCHAR)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
    01434
    01435     if ( DaclSize != sizeof(ACL) ) {
    01436         Dacl = (PACL)CurrentAvailable;
    01437         CurrentAvailable += DaclSize;
    01438
    01439         ntstatus = RtlCreateAcl( Dacl, DaclSize, ACL_REVISION );
    01440
    01441         if ( !NT_SUCCESS(ntstatus) ) {
    01442             goto Cleanup;
    01443         }
    01444     }
    01445
    01446     if ( SaclSize != sizeof(ACL) ) {
    01447         Sacl = (PACL)CurrentAvailable;
    01448         CurrentAvailable += SaclSize;
    01449
    01450         ntstatus = RtlCreateAcl( Sacl, SaclSize, ACL_REVISION );
    01451
    01452         if ( !NT_SUCCESS(ntstatus) ) {
    01453             goto Cleanup;
    01454         }
    01455     }
    01456
    01457     //
    01458     // Allocate a temporary buffer big enough for the biggest ACE.
    01459     //
    01460
    01461     if ((MaxAce = RtlAllocateHeap(
    01462                       HeapHandle, MAKE_TAG( SE_TAG ),
    01463                       MaxAceSize
    01464                       )) == NULL ) {
    01465         ntstatus = STATUS_NO_MEMORY;
    01466         goto Cleanup;
    01467     }
    01468
    01469     //
    01470     // Initialize each ACE, and append it into the end of the DACL or SACL.
    01471     //
    01472
    01473     for (i = 0; i < AceCount; i++) {
    01474         ULONG AceSize;
    01475         PACL CurrentAcl;
    01476
    01477         AceSize = RtlLengthSid(*(AceData[i].Sid));
    01478
    01479         switch (AceData[i].AceType) {
    01480         case ACCESS_ALLOWED_ACE_TYPE:
    01481
    01482             AceSize += sizeof(ACCESS_ALLOWED_ACE);
    01483             CurrentAcl = Dacl;
    01484             ntstatus = RtlpInitializeAllowedAce(
    01485                            MaxAce,
    01486                            (USHORT) AceSize,
    01487                            AceData[i].InheritFlags,
    01488                            AceData[i].AceFlags,
    01489                            AceData[i].Mask,
    01490                            *(AceData[i].Sid)
    01491                            );
    01492             break;
    01493
    01494         case ACCESS_DENIED_ACE_TYPE:
    01495             AceSize += sizeof(ACCESS_DENIED_ACE);
    01496             CurrentAcl = Dacl;
    01497             ntstatus = RtlpInitializeDeniedAce(
    01498                            MaxAce,
    01499                            (USHORT) AceSize,
    01500                            AceData[i].InheritFlags,
    01501                            AceData[i].AceFlags,
    01502                            AceData[i].Mask,
    01503                            *(AceData[i].Sid)
    01504                            );
    01505             break;
    01506
    01507         case SYSTEM_AUDIT_ACE_TYPE:
    01508             AceSize += sizeof(SYSTEM_AUDIT_ACE);
    01509             CurrentAcl = Sacl;
    01510             ntstatus = RtlpInitializeAuditAce(
    01511                            MaxAce,
    01512                            (USHORT) AceSize,
    01513                            AceData[i].InheritFlags,
    01514                            AceData[i].AceFlags,
    01515                            AceData[i].Mask,
    01516                            *(AceData[i].Sid)
    01517                            );
    01518             break;
    01519         }
    01520
    01521         if ( !NT_SUCCESS( ntstatus ) ) {
    01522             goto Cleanup;
    01523         }
    01524
    01525         //
    01526         // Append the initialized ACE to the end of DACL or SACL
    01527         //
    01528
    01529         if (! NT_SUCCESS (ntstatus = RtlAddAce(
    01530                                          CurrentAcl,
    01531                                          ACL_REVISION,
    01532                                          MAXULONG,
    01533                                          MaxAce,
    01534                                          AceSize
    01535                                          ))) {
    01536             goto Cleanup;
    01537         }
    01538     }
    01539
    01540     //
    01541     // Create the security descriptor with absolute pointers to SIDs
    01542     // and ACLs.
    01543     //
    01544     // Owner = OwnerSid
    01545     // Group = GroupSid
    01546     // Dacl  = Dacl
    01547     // Sacl  = Sacl
    01548     //
    01549
    01550     if (! NT_SUCCESS(ntstatus = RtlCreateSecurityDescriptor(
    01551                                     AbsoluteSd,
    01552                                     SECURITY_DESCRIPTOR_REVISION
    01553                                     ))) {
    01554         goto Cleanup;
    01555     }
    01556
    01557     if (! NT_SUCCESS(ntstatus = RtlSetOwnerSecurityDescriptor(
    01558                                     AbsoluteSd,
    01559                                     OwnerSid,
    01560                                     FALSE
    01561                                     ))) {
    01562         goto Cleanup;
    01563     }
    01564
    01565     if (! NT_SUCCESS(ntstatus = RtlSetGroupSecurityDescriptor(
    01566                                     AbsoluteSd,
    01567                                     GroupSid,
    01568                                     FALSE
    01569                                     ))) {
    01570         goto Cleanup;
    01571     }
    01572
    01573     if (! NT_SUCCESS(ntstatus = RtlSetDaclSecurityDescriptor(
    01574                                     AbsoluteSd,
    01575                                     TRUE,
    01576                                     Dacl,
    01577                                     FALSE
    01578                                     ))) {
    01579         goto Cleanup;
    01580     }
    01581
    01582     if (! NT_SUCCESS(ntstatus = RtlSetSaclSecurityDescriptor(
    01583                                     AbsoluteSd,
    01584                                     FALSE,
    01585                                     Sacl,
    01586                                     FALSE
    01587                                     ))) {
    01588         goto Cleanup;
    01589     }
    01590
    01591     //
    01592     // Done
    01593     //
    01594
    01595     ntstatus = STATUS_SUCCESS;
    01596
    01597     //
    01598     // Clean up
    01599     //
    01600
    01601 Cleanup:
    01602     //
    01603     // Either return the security descriptor to the caller or delete it
    01604     //
    01605
    01606     if ( NT_SUCCESS( ntstatus ) ) {
    01607         *NewDescriptor = AbsoluteSd;
    01608     } else if ( AbsoluteSd != NULL ) {
    01609         (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
    01610     }
    01611
    01612     //
    01613     // Delete the temporary ACE
    01614     //
    01615
    01616     if ( MaxAce != NULL ) {
    01617         (void) RtlFreeHeap(HeapHandle, 0, MaxAce);
    01618     }
    01619     return ntstatus;
    01620 }
    01621
    01622
    01623 NTSTATUS
    01624 RtlCreateUserSecurityObject(
    01625     IN  PRTL_ACE_DATA AceData,
    01626     IN  ULONG AceCount,
    01627     IN  PSID OwnerSid,
    01628     IN  PSID GroupSid,
    01629     IN  BOOLEAN IsDirectoryObject,
    01630     IN  PGENERIC_MAPPING GenericMapping,
    01631     OUT PSECURITY_DESCRIPTOR *NewDescriptor
    01632     )
    01633 /*++
    01634
    01635 Routine Description:
    01636
    01637     This function creates the DACL for the security descriptor based on
    01638     on the ACE information specified, and creates the security descriptor
    01639     which becomes the user-mode security object.
    01640
    01641     A sample usage of this function:
    01642
    01643         //
    01644         // Structure that describes the mapping of Generic access rights to
    01645         // object specific access rights for the ConfigurationInfo object.
    01646         //
    01647
    01648         GENERIC_MAPPING WsConfigInfoMapping = {
    01649             STANDARD_RIGHTS_READ            |      // Generic read
    01650                 WKSTA_CONFIG_GUEST_INFO_GET |
    01651                 WKSTA_CONFIG_USER_INFO_GET  |
    01652                 WKSTA_CONFIG_ADMIN_INFO_GET,
    01653             STANDARD_RIGHTS_WRITE |                // Generic write
    01654                 WKSTA_CONFIG_INFO_SET,
    01655             STANDARD_RIGHTS_EXECUTE,               // Generic execute
    01656             WKSTA_CONFIG_ALL_ACCESS                // Generic all
    01657             };
    01658
    01659         //
    01660         // Order matters!  These ACEs are inserted into the DACL in the
    01661         // following order.  Security access is granted or denied based on
    01662         // the order of the ACEs in the DACL.
    01663         //
    01664
    01665         RTL_ACE_DATA AceData[4] = {
    01666             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01667                    GENERIC_ALL,                  &LocalAdminSid},
    01668
    01669             {ACCESS_DENIED_ACE_TYPE,  0, 0,
    01670                    GENERIC_ALL,                  &NetworkSid},
    01671
    01672             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01673                    WKSTA_CONFIG_GUEST_INFO_GET |
    01674                    WKSTA_CONFIG_USER_INFO_GET,   &DomainUsersSid},
    01675
    01676             {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
    01677                    WKSTA_CONFIG_GUEST_INFO_GET,  &DomainGuestsSid}
    01678             };
    01679
    01680         PSECURITY_DESCRIPTOR WkstaSecurityObject;
    01681
    01682
    01683         return RtlCreateUserSecurityObject(
    01684                    AceData,
    01685                    4,
    01686                    LocalSystemSid,
    01687                    LocalSystemSid,
    01688                    FALSE,
    01689                    &WsConfigInfoMapping,
    01690                    &WkstaSecurityObject
    01691                    );
    01692
    01693 Arguments:
    01694
    01695     AceData - Supplies the structure of information that describes the DACL.
    01696
    01697     AceCount - Supplies the number of entries in AceData structure.
    01698
    01699     OwnerSid - Supplies the pointer to the SID of the security descriptor
    01700         owner.
    01701
    01702     GroupSid - Supplies the pointer to the SID of the security descriptor
    01703         primary group.
    01704
    01705     IsDirectoryObject - Supplies the flag which indicates whether the
    01706         user-mode object is a directory object.
    01707
    01708     GenericMapping - Supplies the pointer to a generic mapping array denoting
    01709         the mapping between each generic right to specific rights.
    01710
    01711     NewDescriptor - Returns a pointer to the self-relative security descriptor
    01712         which represents the user-mode object.
    01713
    01714 Return Value:
    01715
    01716     STATUS_SUCCESS - if successful
    01717     STATUS_NO_MEMORY - if cannot allocate memory for DACL, ACEs, and
    01718         security descriptor.
    01719
    01720     Any other status codes returned from the security Rtl routines.
    01721
    01722     NOTE : the user security object created by calling this function may be
    01723                 freed up by calling RtlDeleteSecurityObject().
    01724
    01725 --*/
    01726 {
    01727
    01728     NTSTATUS ntstatus;
    01729     PSECURITY_DESCRIPTOR AbsoluteSd;
    01730     HANDLE TokenHandle;
    01731     PVOID HeapHandle = RtlProcessHeap();
    01732
    01733     ntstatus = RtlCreateAndSetSD(
    01734                    AceData,
    01735                    AceCount,
    01736                    OwnerSid,
    01737                    GroupSid,
    01738                    &AbsoluteSd
    01739                    );
    01740
    01741     if (! NT_SUCCESS(ntstatus)) {
    01742         return ntstatus;
    01743     }
    01744
    01745     ntstatus = NtOpenProcessToken(
    01746                    NtCurrentProcess(),
    01747                    TOKEN_QUERY,
    01748                    &TokenHandle
    01749                    );
    01750
    01751     if (! NT_SUCCESS(ntstatus)) {
    01752         (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
    01753         return ntstatus;
    01754     }
    01755
    01756     //
    01757     // Create the security object (a user-mode object is really a pseudo-
    01758     // object represented by a security descriptor that have relative
    01759     // pointers to SIDs and ACLs).  This routine allocates the memory to
    01760     // hold the relative security descriptor so the memory allocated for the
    01761     // DACL, ACEs, and the absolute descriptor can be freed.
    01762     //
    01763     ntstatus = RtlNewSecurityObject(
    01764                    NULL,                   // Parent descriptor
    01765                    AbsoluteSd,             // Creator descriptor
    01766                    NewDescriptor,          // Pointer to new descriptor
    01767                    IsDirectoryObject,      // Is directory object
    01768                    TokenHandle,            // Token
    01769                    GenericMapping          // Generic mapping
    01770                    );
    01771
    01772     (void) NtClose(TokenHandle);
    01773
    01774     //
    01775     // Free dynamic memory before returning
    01776     //
    01777     (void) RtlFreeHeap(HeapHandle, 0, AbsoluteSd);
    01778     return ntstatus;
    01779 }
    01780
    01781
    01782
    01783
    01784
    01785 NTSTATUS
    01786 RtlConvertToAutoInheritSecurityObject(
    01787     IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
    01788     IN PSECURITY_DESCRIPTOR CurrentSecurityDescriptor,
    01789     OUT PSECURITY_DESCRIPTOR *NewSecurityDescriptor,
    01790     IN GUID *ObjectType OPTIONAL,
    01791     IN BOOLEAN IsDirectoryObject,
    01792     IN PGENERIC_MAPPING GenericMapping
    01793     )
    01794 /*++
    01795
    01796 Routine Description:
    01797
    01798     This is a converts a security descriptor whose ACLs are not marked
    01799     as AutoInherit to a security descriptor whose ACLs are marked as
    01800     AutoInherit.
    01801
    01802     See further detailed description on ConvertToAutoInheritPrivateObjectSecurity.
    01803
    01804 Arguments:
    01805
    01806     ParentDescriptor - Supplies the Security Descriptor for the parent
    01807         directory under which a object exists.  If there is
    01808         no parent directory, then this argument is specified as NULL.
    01809
    01810     CurrentSecurityDescriptor - Supplies a pointer to the objects security descriptor
    01811         that is going to be altered by this procedure.
    01812
    01813     NewSecurityDescriptor Points to a pointer that is to be made to point to the
    01814         newly allocated self-relative security descriptor. When no
    01815         longer needed, this descriptor must be freed using
    01816         DestroyPrivateObjectSecurity().
    01817
    01818     ObjectType - GUID of the object type being created.  If the object being
    01819         created has no GUID associated with it, then this argument is
    01820         specified as NULL.
    01821
    01822     IsDirectoryObject - Specifies if the object is a
    01823         directory object.  A value of TRUE indicates the object is a
    01824         container of other objects.
    01825
    01826     GenericMapping - Supplies a pointer to a generic mapping array denoting
    01827         the mapping between each generic right to specific rights.
    01828
    01829 Return Value:
    01830
    01831     STATUS_SUCCESS - The operation was successful.
    01832
    01833     STATUS_UNKNOWN_REVISION - Indicates the source ACL is a revision that
    01834         is unknown to this routine.  (Only revision 2 ACLs are support by this routine.)
    01835
    01836     STATUS_INVALID_ACL - The structure of one of the ACLs in invalid.
    01837
    01838
    01839
    01840 --*/
    01841 {
    01842
    01843     //
    01844     // Simply call the corresponding Rtlp routine telling it which allocator
    01845     //  to use.
    01846     //
    01847
    01848     return RtlpConvertToAutoInheritSecurityObject(
    01849                             ParentDescriptor,
    01850                             CurrentSecurityDescriptor,
    01851                             NewSecurityDescriptor,
    01852                             ObjectType,
    01853                             IsDirectoryObject,
    01854                             GenericMapping );
    01855
    01856 }
    01857
    01858
    01859 NTSTATUS
    01860 RtlDefaultNpAcl(
    01861     OUT PACL * pAcl
    01862     )
    01863 /*++
    01864
    01865 Routine Description:
    01866
    01867     This routine constructs a default ACL to be applied to
    01868     named pipe objects when the caller has not specified one.
    01869     See NT bug 131090.
    01870
    01871     The ACL constructed is as follows:
    01872
    01873     Need to build an ACL that looks like the following:
    01874
    01875      Local System : F
    01876      Administrators: F
    01877      Owner: F
    01878      Everyone: R
    01879
    01880      The owner is determined by querying the currently effective
    01881      toke and extracting the default owner.
    01882
    01883 Arguments:
    01884
    01885     pAcl - Receives a pointer to an ACL to apply to the named pipe
    01886         being created.  Guaranteed to be NULL on return if an error
    01887         occurs.
    01888
    01889         This must be freed by calling RtlFreeHeap.
    01890
    01891 Return Value:
    01892
    01893     NT Status.
    01894
    01895 --*/
    01896 {
    01897     SID_IDENTIFIER_AUTHORITY    NtAuthority         = SECURITY_NT_AUTHORITY;
    01898     SID_IDENTIFIER_AUTHORITY    CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
    01899     SID_IDENTIFIER_AUTHORITY    WorldSidAuthority   = SECURITY_WORLD_SID_AUTHORITY;
    01900
    01901     ULONG AclSize         = 0;
    01902     NTSTATUS Status       = STATUS_SUCCESS;
    01903     ULONG ReturnLength    = 0;
    01904     PTOKEN_OWNER OwnerSid = NULL;
    01905
    01906     HANDLE hToken;
    01907
    01908     //
    01909     // Initialize OUT parameters
    01910     //
    01911
    01912     *pAcl = NULL;
    01913
    01914     //
    01915     // Open thread token
    01916     //
    01917
    01918     Status = NtOpenThreadToken(
    01919                  NtCurrentThread(),
    01920                  TOKEN_QUERY,
    01921                  TRUE,
    01922                  &hToken
    01923                  );
    01924
    01925     if (STATUS_NO_TOKEN == Status) {
    01926
    01927         //
    01928         // Not impersonating, get process token
    01929         //
    01930
    01931         Status = NtOpenProcessToken(
    01932                      NtCurrentProcess(),
    01933                      TOKEN_QUERY,
    01934                      &hToken
    01935                      );
    01936     }
    01937
    01938     if (NT_SUCCESS( Status )) {
    01939
    01940         //
    01941         // Get the default owner
    01942         //
    01943
    01944         Status = NtQueryInformationToken (
    01945                      hToken,
    01946                      TokenOwner,
    01947                      NULL,
    01948                      0,
    01949                      &ReturnLength
    01950                      );
    01951
    01952         if (STATUS_BUFFER_TOO_SMALL == Status) {
    01953
    01954             OwnerSid = (PTOKEN_OWNER)RtlAllocateHeap( RtlProcessHeap(), 0, ReturnLength );
    01955
    01956             if (OwnerSid) {
    01957
    01958                 Status = NtQueryInformationToken (
    01959                              hToken,
    01960                              TokenOwner,
    01961                              OwnerSid,
    01962                              ReturnLength,
    01963                              &ReturnLength
    01964                              );
    01965
    01966                 if (NT_SUCCESS( Status )) {
    01967
    01968                     //
    01969                     // Compute the size needed
    01970                     //
    01971
    01972                     UCHAR SidBuffer[16];
    01973                     ASSERT( 16 == RtlLengthRequiredSid( 2 ));
    01974
    01975                     AclSize += RtlLengthRequiredSid( 1 );   // LocalSystem Sid
    01976                     AclSize += RtlLengthRequiredSid( 2 );   // Administrators
    01977                     AclSize += RtlLengthRequiredSid( 1 );   // Everyone (World)
    01978
    01979                     AclSize += RtlLengthSid( OwnerSid->Owner );   // Owner
    01980
    01981                     AclSize += sizeof( ACL );               // Header
    01982                     AclSize += 4 * (sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG ));
    01983
    01984                     //
    01985                     // Allocate the Acl out of the local process heap
    01986                     //
    01987
    01988                     *pAcl = (PACL)RtlAllocateHeap( RtlProcessHeap(), 0, AclSize );
    01989
    01990                     if (*pAcl != NULL) {
    01991
    01992                         RtlCreateAcl( *pAcl, AclSize, ACL_REVISION );
    01993
    01994                         //
    01995                         // Create each SID in turn and copy the resultant ACE into
    01996                         // the new ACL
    01997                         //
    01998
    01999                         //
    02000                         // Local System - Generic All
    02001                         //
    02002
    02003                         RtlInitializeSid( SidBuffer, &NtAuthority, 1);
    02004                         *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
    02005                         RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
    02006
    02007                         //
    02008                         // Admins - Generic All
    02009                         //
    02010
    02011                         RtlInitializeSid( SidBuffer, &NtAuthority, 2);
    02012                         *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    02013                         *(RtlSubAuthoritySid( SidBuffer, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
    02014                         RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, (PSID)SidBuffer );
    02015
    02016                         //
    02017                         // Owner - Generic All
    02018                         //
    02019
    02020                         RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_ALL, OwnerSid->Owner );
    02021
    02022                         //
    02023                         // World - Generic Read
    02024                         //
    02025
    02026                         RtlInitializeSid( SidBuffer, &WorldSidAuthority, 1 );
    02027                         *(RtlSubAuthoritySid( SidBuffer, 0 )) = SECURITY_WORLD_RID;
    02028                         RtlAddAccessAllowedAce( *pAcl, ACL_REVISION, GENERIC_READ, (PSID)SidBuffer );
    02029
    02030                     } else {
    02031
    02032                         Status = STATUS_NO_MEMORY;
    02033                     }
    02034                 }
    02035
    02036                 RtlFreeHeap( RtlProcessHeap(), 0, OwnerSid );
    02037
    02038             } else {
    02039
    02040                 Status = STATUS_NO_MEMORY;
    02041             }
    02042         }
    02043
    02044         NtClose( hToken );
    02045     }
    02046
    02047     if (!NT_SUCCESS( Status )) {
    02048
    02049         //
    02050         // Something failed, clean up OUT
    02051         // parameters.
    02052         //
    02053
    02054         if (*pAcl != NULL) {
    02055             RtlFreeHeap( RtlProcessHeap(), 0, *pAcl );
    02056             *pAcl = NULL;
    02057         }
    02058     }
    02059
    02060     return( Status );
    02061 }
    02062