test: acledit.c Source File

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

# acledit.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     Acledit.c
    00008
    00009 Abstract:
    00010
    00011     This Module implements the Acl rtl editing functions that are defined in
    00012     ntseapi.h
    00013
    00014 Author:
    00015
    00016     Gary Kimura     (GaryKi)    9-Nov-1989
    00017
    00018 Environment:
    00019
    00020     Pure Runtime Library Routine
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026 #include <ntrtlp.h>
    00027 #include <seopaque.h>
    00028
    00029 //
    00030 //  Define the local macros and procedure for this module
    00031 //
    00032
    00033 //
    00034 //  Return a pointer to the first Ace in an Acl (even if the Acl is empty).
    00035 //
    00036 //      PACE_HEADER
    00037 //      FirstAce (
    00038 //          IN PACL Acl
    00039 //          );
    00040 //
    00041
    00042 #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))
    00043
    00044 //
    00045 //  Return a pointer to the next Ace in a sequence (even if the input
    00046 //  Ace is the one in the sequence).
    00047 //
    00048 //      PACE_HEADER
    00049 //      NextAce (
    00050 //          IN PACE_HEADER Ace
    00051 //          );
    00052 //
    00053
    00054 #define NextAce(Ace) ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize))
    00055
    00056 #define LongAligned( ptr )  (LongAlign(ptr) == ((PVOID)(ptr)))
    00057 #define WordAligned( ptr )  (WordAlign(ptr) == ((PVOID)(ptr)))
    00058
    00059
    00060     VOID
    00061 RtlpAddData (
    00062     IN PVOID From,
    00063     IN ULONG FromSize,
    00064     IN PVOID To,
    00065     IN ULONG ToSize
    00066     );
    00067
    00068 VOID
    00069 RtlpDeleteData (
    00070     IN PVOID Data,
    00071     IN ULONG RemoveSize,
    00072     IN ULONG TotalSize
    00073     );
    00074
    00075 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
    00076 #pragma alloc_text(PAGE,RtlpAddData)
    00077 #pragma alloc_text(PAGE,RtlpDeleteData)
    00078 #pragma alloc_text(PAGE,RtlCreateAcl)
    00079 #pragma alloc_text(PAGE,RtlValidAcl)
    00080 #pragma alloc_text(PAGE,RtlQueryInformationAcl)
    00081 #pragma alloc_text(PAGE,RtlSetInformationAcl)
    00082 #pragma alloc_text(PAGE,RtlAddAce)
    00083 #pragma alloc_text(PAGE,RtlDeleteAce)
    00084 #pragma alloc_text(PAGE,RtlGetAce)
    00085 #pragma alloc_text(PAGE,RtlAddAccessAllowedAce)
    00086 #pragma alloc_text(PAGE,RtlAddAccessAllowedAceEx)
    00087 #pragma alloc_text(PAGE,RtlAddAccessAllowedObjectAce)
    00088 #pragma alloc_text(PAGE,RtlAddAccessDeniedAce)
    00089 #pragma alloc_text(PAGE,RtlAddAccessDeniedAceEx)
    00090 #pragma alloc_text(PAGE,RtlAddAccessDeniedObjectAce)
    00091 #pragma alloc_text(PAGE,RtlAddAuditAccessAce)
    00092 #pragma alloc_text(PAGE,RtlAddAuditAccessAceEx)
    00093 #pragma alloc_text(PAGE,RtlAddAuditAccessObjectAce)
    00094 #pragma alloc_text(PAGE,RtlFirstFreeAce)
    00095 #endif
    00096
    00097
    00098 NTSTATUS
    00099 RtlCreateAcl (
    00100     IN PACL Acl,
    00101     IN ULONG AclLength,
    00102     IN ULONG AclRevision
    00103     )
    00104
    00105 /*++
    00106
    00107 Routine Description:
    00108
    00109     This routine initializes an ACL data structure.  After initialization
    00110     it is an ACL with no ACE (i.e., a deny all access type ACL)
    00111
    00112 Arguments:
    00113
    00114     Acl - Supplies the buffer containing the ACL being initialized
    00115
    00116     AclLength - Supplies the length of the ace buffer in bytes
    00117
    00118     AclRevision - Supplies the revision for this Acl
    00119
    00120 Return Value:
    00121
    00122     NTSTATUS - STATUS_SUCCESS if successful
    00123
    00124                STATUS_BUFFER_TOO_SMALL if the AclLength is too small,
    00125
    00126                STATUS_INVALID_PARAMETER if the revision is out of range
    00127
    00128 --*/
    00129
    00130 {
    00131     RTL_PAGED_CODE();
    00132
    00133     //
    00134     //  Check to see the size of the buffer is large enough to hold at
    00135     //  least the ACL header
    00136     //
    00137
    00138     if (AclLength < sizeof(ACL)) {
    00139
    00140         //
    00141         //  Buffer to small even for the ACL header
    00142         //
    00143
    00144         return STATUS_BUFFER_TOO_SMALL;
    00145
    00146     }
    00147
    00148     //
    00149     //  Check to see if the revision is currently valid.  Later versions
    00150     //  of this procedure might accept more revision levels
    00151     //
    00152
    00153     if (AclRevision < MIN_ACL_REVISION || AclRevision > MAX_ACL_REVISION) {
    00154
    00155         //
    00156         //  Revision not current
    00157         //
    00158
    00159         return STATUS_INVALID_PARAMETER;
    00160
    00161     }
    00162
    00163     if ( AclLength > MAXUSHORT ) {
    00164
    00165         return STATUS_INVALID_PARAMETER;
    00166     }
    00167
    00168     //
    00169     //  Initialize the ACL
    00170     //
    00171
    00172     Acl->AclRevision = (UCHAR)AclRevision;  // Used to hardwire ACL_REVISION2 here
    00173     Acl->Sbz1 = 0;
    00174     Acl->AclSize = (USHORT) (AclLength & 0xfffc);
    00175     Acl->AceCount = 0;
    00176     Acl->Sbz2 = 0;
    00177
    00178     //
    00179     //  And return to our caller
    00180     //
    00181
    00182     return STATUS_SUCCESS;
    00183 }
    00184
    00185
    00186 BOOLEAN
    00187 RtlValidAcl (
    00188     IN PACL Acl
    00189     )
    00190
    00191 /*++
    00192
    00193 Routine Description:
    00194
    00195     This procedure validates an ACL.
    00196
    00197     This involves validating the revision level of the ACL and ensuring
    00198     that the number of ACEs specified in the AceCount fit in the space
    00199     specified by the AclSize field of the ACL header.
    00200
    00201 Arguments:
    00202
    00203     Acl - Pointer to the ACL structure to validate.
    00204
    00205 Return Value:
    00206
    00207     BOOLEAN - TRUE if the structure of Acl is valid.
    00208
    00209 --*/
    00210
    00211 {
    00212     RTL_PAGED_CODE();
    00213
    00214     try {
    00215         PACE_HEADER Ace;
    00216         PISID Sid;
    00217         PISID Sid2;
    00218         ULONG i;
    00219         UCHAR AclRevision = ACL_REVISION2;
    00220
    00221
    00222         //
    00223         //  Check the ACL revision level
    00224         //
    00225         if (!ValidAclRevision(Acl)) {
    00226             return(FALSE);
    00227         }
    00228
    00229
    00230         if (!WordAligned(&Acl->AclSize)) {
    00231             return(FALSE);
    00232         }
    00233
    00234         if (Acl->AclSize < sizeof(ACL)) {
    00235             return(FALSE);
    00236         }
    00237         //
    00238         // Validate all of the ACEs.
    00239         //
    00240
    00241         Ace = ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)));
    00242
    00243         for (i = 0; i < Acl->AceCount; i++) {
    00244
    00245             //
    00246             //  Check to make sure we haven't overrun the Acl buffer
    00247             //  with our ace pointer.  Make sure the ACE_HEADER is in
    00248             //  the ACL also.
    00249             //
    00250
    00251             if ((PUCHAR)Ace + sizeof(ACE_HEADER) >= ((PUCHAR)Acl + Acl->AclSize)) {
    00252                 return(FALSE);
    00253             }
    00254
    00255             if (!WordAligned(&Ace->AceSize)) {
    00256                 return(FALSE);
    00257             }
    00258
    00259             if ((PUCHAR)Ace + Ace->AceSize > ((PUCHAR)Acl + Acl->AclSize)) {
    00260                 return(FALSE);
    00261             }
    00262
    00263             //
    00264             // It is now safe to reference fields in the ACE header.
    00265             //
    00266
    00267             //
    00268             // The ACE header fits into the ACL, if this is a known type of ACE,
    00269             // make sure the SID is within the bounds of the ACE
    00270             //
    00271
    00272             if (IsKnownAceType(Ace)) {
    00273
    00274                 if (!LongAligned(Ace->AceSize)) {
    00275                     return(FALSE);
    00276                 }
    00277
    00278                 if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + sizeof(SID) - sizeof(ULONG)) {
    00279                     return(FALSE);
    00280                 }
    00281
    00282                 //
    00283                 // It's now safe to reference the parts of the SID structure, though
    00284                 // not the SID itself.
    00285                 //
    00286
    00287                 Sid = (PISID) & (((PKNOWN_ACE)Ace)->SidStart);
    00288
    00289                 if (Sid->Revision != SID_REVISION) {
    00290                     return(FALSE);
    00291                 }
    00292
    00293                 if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
    00294                     return(FALSE);
    00295                 }
    00296
    00297                 //
    00298                 // SeLengthSid computes the size of the SID based on the subauthority count,
    00299                 // so it is safe to use even though we don't know that the body of the SID
    00300                 // is safe to reference.
    00301                 //
    00302
    00303                 if (Ace->AceSize < sizeof(KNOWN_ACE) - sizeof(ULONG) + SeLengthSid( Sid )) {
    00304                     return(FALSE);
    00305                 }
    00306
    00307
    00308             //
    00309             // If it's a compound ACE, then perform roughly the same set of tests, but
    00310             // check the validity of both SIDs.
    00311             //
    00312
    00313             } else if (IsCompoundAceType(Ace)) {
    00314
    00315                 //
    00316                 // Compound ACEs became valid in revision 3
    00317                 //
    00318                 if ( Acl->AclRevision < ACL_REVISION3 ) {
    00319                     return FALSE;
    00320                 }
    00321
    00322                 if (!LongAligned(Ace->AceSize)) {
    00323                     return(FALSE);
    00324                 }
    00325
    00326                 if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + sizeof(SID)) {
    00327                     return(FALSE);
    00328                 }
    00329
    00330                 //
    00331                 // The only currently defined Compound ACE is an Impersonation ACE.
    00332                 //
    00333
    00334                 if (((PKNOWN_COMPOUND_ACE)Ace)->CompoundAceType != COMPOUND_ACE_IMPERSONATION) {
    00335                     return(FALSE);
    00336                 }
    00337
    00338                 //
    00339                 // Examine the first SID and make sure it's structurally valid,
    00340                 // and it lies within the boundaries of the ACE.
    00341                 //
    00342
    00343                 Sid = (PISID) & (((PKNOWN_COMPOUND_ACE)Ace)->SidStart);
    00344
    00345                 if (Sid->Revision != SID_REVISION) {
    00346                     return(FALSE);
    00347                 }
    00348
    00349                 if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
    00350                     return(FALSE);
    00351                 }
    00352
    00353                 //
    00354                 // Compound ACEs contain two SIDs.  Make sure this ACE is large enough to contain
    00355                 // not only the first SID, but the body of the 2nd.
    00356                 //
    00357
    00358                 if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + sizeof(SID)) {
    00359                     return(FALSE);
    00360                 }
    00361
    00362                 //
    00363                 // It is safe to reference the interior of the 2nd SID.
    00364                 //
    00365
    00366                 Sid2 = (PISID) ((PUCHAR)Sid + SeLengthSid( Sid ));
    00367
    00368                 if (Sid2->Revision != SID_REVISION) {
    00369                     return(FALSE);
    00370                 }
    00371
    00372                 if (Sid2->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
    00373                     return(FALSE);
    00374                 }
    00375
    00376                 if (Ace->AceSize < sizeof(KNOWN_COMPOUND_ACE) - sizeof(ULONG) + SeLengthSid( Sid ) + SeLengthSid( Sid2 )) {
    00377                     return(FALSE);
    00378                 }
    00379
    00380
    00381             //
    00382             // If it's an object ACE, then perform roughly the same set of tests.
    00383             //
    00384
    00385             } else if (IsObjectAceType(Ace)) {
    00386                 ULONG GuidSize=0;
    00387
    00388                 //
    00389                 // Object ACEs became valid in revision 4
    00390                 //
    00391                 if ( Acl->AclRevision < ACL_REVISION4 ) {
    00392                     return FALSE;
    00393                 }
    00394
    00395                 if (!LongAligned(Ace->AceSize)) {
    00396                     return(FALSE);
    00397                 }
    00398
    00399                 //
    00400                 // Ensure there is room for the ACE header.
    00401                 //
    00402                 if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG)) {
    00403                     return(FALSE);
    00404                 }
    00405
    00406
    00407                 //
    00408                 // Ensure there is room for the GUIDs and SID header
    00409                 //
    00410                 if ( RtlObjectAceObjectTypePresent( Ace ) ) {
    00411                     GuidSize += sizeof(GUID);
    00412                 }
    00413
    00414                 if ( RtlObjectAceInheritedObjectTypePresent( Ace ) ) {
    00415                     GuidSize += sizeof(GUID);
    00416                 }
    00417
    00418                 if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG) + GuidSize + sizeof(SID)) {
    00419                     return(FALSE);
    00420                 }
    00421
    00422                 //
    00423                 // It's now safe to reference the parts of the SID structure, though
    00424                 // not the SID itself.
    00425                 //
    00426
    00427                 Sid = (PISID) RtlObjectAceSid( Ace );
    00428
    00429                 if (Sid->Revision != SID_REVISION) {
    00430                     return(FALSE);
    00431                 }
    00432
    00433                 if (Sid->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES) {
    00434                     return(FALSE);
    00435                 }
    00436
    00437                 if (Ace->AceSize < sizeof(KNOWN_OBJECT_ACE) - sizeof(ULONG) + GuidSize + SeLengthSid( Sid ) ) {
    00438                     return(FALSE);
    00439                 }
    00440             }
    00441
    00442             //
    00443             //  And move Ace to the next ace position
    00444             //
    00445
    00446             Ace = ((PVOID)((PUCHAR)(Ace) + ((PACE_HEADER)(Ace))->AceSize));
    00447         }
    00448
    00449         return(TRUE);
    00450
    00451     } except(EXCEPTION_EXECUTE_HANDLER) {
    00452
    00453         return FALSE;
    00454     }
    00455
    00456 }
    00457
    00458
    00459 NTSTATUS
    00460 RtlQueryInformationAcl (
    00461     IN PACL Acl,
    00462     OUT PVOID AclInformation,
    00463     IN ULONG AclInformationLength,
    00464     IN ACL_INFORMATION_CLASS AclInformationClass
    00465     )
    00466
    00467 /*++
    00468
    00469 Routine Description:
    00470
    00471     This routine returns to the caller information about an ACL.  The requested
    00472     information can be AclRevisionInformation, or AclSizeInformation.
    00473
    00474 Arguments:
    00475
    00476     Acl - Supplies the Acl being examined
    00477
    00478     AclInformation - Supplies the buffer to receive the information being
    00479         requested
    00480
    00481     AclInformationLength - Supplies the length of the AclInformation buffer
    00482         in bytes
    00483
    00484     AclInformationClass - Supplies the type of information being requested
    00485
    00486 Return Value:
    00487
    00488     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
    00489         status otherwise
    00490
    00491 --*/
    00492
    00493 {
    00494     PACL_REVISION_INFORMATION RevisionInfo;
    00495     PACL_SIZE_INFORMATION SizeInfo;
    00496
    00497
    00498     PVOID FirstFree;
    00499     NTSTATUS Status;
    00500
    00501     RTL_PAGED_CODE();
    00502
    00503     //
    00504     //  Check the ACL revision level
    00505     //
    00506
    00507     if (!ValidAclRevision( Acl )) {
    00508
    00509         return STATUS_INVALID_PARAMETER;
    00510
    00511     }
    00512
    00513     //
    00514     //  Case on the information class being requested
    00515     //
    00516
    00517     switch (AclInformationClass) {
    00518
    00519     case AclRevisionInformation:
    00520
    00521         //
    00522         //  Make sure the buffer size is correct
    00523         //
    00524
    00525         if (AclInformationLength < sizeof(ACL_REVISION_INFORMATION)) {
    00526
    00527             return STATUS_BUFFER_TOO_SMALL;
    00528
    00529         }
    00530
    00531         //
    00532         //  Get the Acl revision and return
    00533         //
    00534
    00535         RevisionInfo = (PACL_REVISION_INFORMATION)AclInformation;
    00536         RevisionInfo->AclRevision = Acl->AclRevision;
    00537
    00538         break;
    00539
    00540     case AclSizeInformation:
    00541
    00542         //
    00543         //  Make sure the buffer size is correct
    00544         //
    00545
    00546         if (AclInformationLength < sizeof(ACL_SIZE_INFORMATION)) {
    00547
    00548             return STATUS_BUFFER_TOO_SMALL;
    00549
    00550         }
    00551
    00552         //
    00553         //  Locate the first free spot in the Acl
    00554         //
    00555
    00556         if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    00557
    00558             //
    00559             //  The input Acl is ill-formed
    00560             //
    00561
    00562             return STATUS_INVALID_PARAMETER;
    00563
    00564         }
    00565
    00566         //
    00567         //  Given a pointer to the first free spot we can now easily compute
    00568         //  the number of free bytes and used bytes in the Acl.
    00569         //
    00570
    00571         SizeInfo = (PACL_SIZE_INFORMATION)AclInformation;
    00572         SizeInfo->AceCount = Acl->AceCount;
    00573
    00574         if (FirstFree == NULL) {
    00575
    00576             //
    00577             //  With a null first free we don't have any free space in the Acl
    00578             //
    00579
    00580             SizeInfo->AclBytesInUse = Acl->AclSize;
    00581
    00582             SizeInfo->AclBytesFree = 0;
    00583
    00584         } else {
    00585
    00586             //
    00587             //  The first free is not null so we have some free room left in
    00588             //  the acl
    00589             //
    00590
    00591             SizeInfo->AclBytesInUse = (ULONG)((PUCHAR)FirstFree - (PUCHAR)Acl);
    00592
    00593             SizeInfo->AclBytesFree = Acl->AclSize - SizeInfo->AclBytesInUse;
    00594
    00595         }
    00596
    00597         break;
    00598
    00599     default:
    00600
    00601         return STATUS_INVALID_INFO_CLASS;
    00602
    00603     }
    00604
    00605     //
    00606     //  and return to our caller
    00607     //
    00608
    00609     return STATUS_SUCCESS;
    00610 }
    00611
    00612
    00613 NTSTATUS
    00614 RtlSetInformationAcl (
    00615     IN PACL Acl,
    00616     IN PVOID AclInformation,
    00617     IN ULONG AclInformationLength,
    00618     IN ACL_INFORMATION_CLASS AclInformationClass
    00619     )
    00620
    00621 /*++
    00622
    00623 Routine Description:
    00624
    00625     This routine sets the state of an ACL.  For now only the revision
    00626     level can be set and for now only a revision level of 1 is accepted
    00627     so this procedure is rather simple
    00628
    00629 Arguments:
    00630
    00631     Acl - Supplies the Acl being altered
    00632
    00633     AclInformation - Supplies the buffer containing the information being
    00634         set
    00635
    00636     AclInformationLength - Supplies the length of the Acl information buffer
    00637
    00638     AclInformationClass - Supplies the type of information begin set
    00639
    00640 Return Value:
    00641
    00642     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
    00643         status otherwise
    00644
    00645 --*/
    00646
    00647 {
    00648     PACL_REVISION_INFORMATION RevisionInfo;
    00649
    00650     RTL_PAGED_CODE();
    00651
    00652     //
    00653     //  Check the ACL revision level
    00654     //
    00655
    00656     if (!ValidAclRevision( Acl )) {
    00657
    00658         return STATUS_INVALID_PARAMETER;
    00659
    00660     }
    00661
    00662     //
    00663     //  Case on the information class being requested
    00664     //
    00665
    00666     switch (AclInformationClass) {
    00667
    00668     case AclRevisionInformation:
    00669
    00670         //
    00671         //  Make sure the buffer size is correct
    00672         //
    00673
    00674         if (AclInformationLength < sizeof(ACL_REVISION_INFORMATION)) {
    00675
    00676             return STATUS_BUFFER_TOO_SMALL;
    00677
    00678         }
    00679
    00680         //
    00681         //  Get the Acl requested ACL revision level
    00682         //
    00683
    00684         RevisionInfo = (PACL_REVISION_INFORMATION)AclInformation;
    00685
    00686         //
    00687         //  Don't let them lower the revision of an ACL.
    00688         //
    00689
    00690         if (RevisionInfo->AclRevision < Acl->AclRevision ) {
    00691
    00692             return STATUS_INVALID_PARAMETER;
    00693         }
    00694
    00695         //
    00696         // Assign the new revision.
    00697         //
    00698
    00699         Acl->AclRevision = (UCHAR)RevisionInfo->AclRevision;
    00700
    00701         break;
    00702
    00703     default:
    00704
    00705         return STATUS_INVALID_INFO_CLASS;
    00706
    00707     }
    00708
    00709     //
    00710     //  and return to our caller
    00711     //
    00712
    00713     return STATUS_SUCCESS;
    00714 }
    00715
    00716
    00717 NTSTATUS
    00718 RtlAddAce (
    00719     IN OUT PACL Acl,
    00720     IN ULONG AceRevision,
    00721     IN ULONG StartingAceIndex,
    00722     IN PVOID AceList,
    00723     IN ULONG AceListLength
    00724     )
    00725
    00726 /*++
    00727
    00728 Routine Description:
    00729
    00730     This routine adds a string of ACEs to an ACL.
    00731
    00732 Arguments:
    00733
    00734     Acl - Supplies the Acl being modified
    00735
    00736     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    00737
    00738     StartingAceIndex - Supplies the ACE index which will be the index of
    00739         the first ace inserted in the acl. 0 for the beginning of the list
    00740         and MAXULONG for the end of the list.
    00741
    00742     AceList - Supplies the list of Aces to be added to the Acl
    00743
    00744     AceListLength - Supplies the size, in bytes, of the AceList buffer
    00745
    00746 Return Value:
    00747
    00748     NTSTATUS - STATUS_SUCCESS if successful, and an appropriate error
    00749         status otherwise
    00750
    00751 --*/
    00752
    00753 {
    00754     PVOID FirstFree;
    00755
    00756     PACE_HEADER Ace;
    00757     ULONG NewAceCount;
    00758
    00759     PVOID AcePosition;
    00760     ULONG i;
    00761     UCHAR NewRevision;
    00762
    00763     RTL_PAGED_CODE();
    00764
    00765     //
    00766     //  Check the ACL structure
    00767     //
    00768
    00769     if (!RtlValidAcl(Acl)) {
    00770
    00771         return STATUS_INVALID_PARAMETER;
    00772
    00773     }
    00774
    00775     //
    00776     //  Locate the first free ace and check to see that the Acl is
    00777     //  well formed.
    00778     //
    00779
    00780     if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    00781
    00782         return STATUS_INVALID_PARAMETER;
    00783
    00784     }
    00785
    00786     //
    00787     // If the AceRevision is greater than the ACL revision, then we want to
    00788     // increase the ACL revision to be the same as the new ACE revision.
    00789     // We can do this because our previously defined ACE types ( 0 -> 3 ) have
    00790     // not changed structure nor been discontinued in the new revision.  So
    00791     // we can bump the revision and the older types will not be misinterpreted.
    00792     //
    00793     // Compute what the final revision of the ACL is going to be, and save it
    00794     // for later so we can update it once we know we're going to succeed.
    00795     //
    00796
    00797     NewRevision = (UCHAR)AceRevision > Acl->AclRevision ? (UCHAR)AceRevision : Acl->AclRevision;
    00798
    00799     //
    00800     // Check that the AceList is well formed, we do this by simply zooming
    00801     // down the Ace list until we're equal to or have exceeded the ace list
    00802     // length.  If we are equal to the length then we're well formed otherwise
    00803     // we're ill-formed.  We'll also calculate how many Ace's there are
    00804     // in the AceList
    00805     //
    00806     // In addition, now we have to make sure that we haven't been handed an
    00807     // ACE type that is inappropriate for the AceRevision that was passed
    00808     // in.
    00809     //
    00810
    00811     for (Ace = AceList, NewAceCount = 0;
    00812          Ace < (PACE_HEADER)((PUCHAR)AceList + AceListLength);
    00813          Ace = NextAce( Ace ), NewAceCount++) {
    00814
    00815         //
    00816         // Ensure the ACL revision allows this ACE type.
    00817         //
    00818
    00819         if ( Ace->AceType <= ACCESS_MAX_MS_V2_ACE_TYPE ) {
    00820             // V2 ACE are always valid.
    00821         } else if ( Ace->AceType <= ACCESS_MAX_MS_V3_ACE_TYPE ) {
    00822             if ( AceRevision < ACL_REVISION3 ) {
    00823                 return STATUS_INVALID_PARAMETER;
    00824             }
    00825         } else if ( Ace->AceType <= ACCESS_MAX_MS_V4_ACE_TYPE ) {
    00826             if ( AceRevision < ACL_REVISION4 ) {
    00827                 return STATUS_INVALID_PARAMETER;
    00828             }
    00829         }
    00830     }
    00831
    00832     //
    00833     //  Check to see if we've exceeded the ace list length
    00834     //
    00835
    00836     if (Ace > (PACE_HEADER)((PUCHAR)AceList + AceListLength)) {
    00837
    00838         return STATUS_INVALID_PARAMETER;
    00839
    00840     }
    00841
    00842     //
    00843     //  Check to see if there is enough room in the Acl to store the additional
    00844     //  Ace list
    00845     //
    00846
    00847     if (FirstFree == NULL ||
    00848         (PUCHAR)FirstFree + AceListLength > (PUCHAR)Acl + Acl->AclSize) {
    00849
    00850         return STATUS_BUFFER_TOO_SMALL;
    00851
    00852     }
    00853
    00854     //
    00855     //  All of the input has checked okay, we now need to locate the position
    00856     //  where to insert the new ace list.  We won't check the acl for
    00857     //  validity because we did earlier when got the first free ace position.
    00858     //
    00859
    00860     AcePosition = FirstAce( Acl );
    00861
    00862     for (i = 0; i < StartingAceIndex && i < Acl->AceCount; i++) {
    00863
    00864         AcePosition = NextAce( AcePosition );
    00865
    00866     }
    00867
    00868     //
    00869     //  Now Ace points to where we want to insert the ace list,  We do the
    00870     //  insertion by adding ace list to the acl and shoving over the remainder
    00871     //  of the list down the acl.  We know this will work because we earlier
    00872     //  check to make sure the new acl list will fit in the acl size
    00873     //
    00874
    00875     RtlpAddData( AceList, AceListLength,
    00876              AcePosition, (ULONG) ((PUCHAR)FirstFree - (PUCHAR)AcePosition));
    00877
    00878     //
    00879     //  Update the Acl Header
    00880     //
    00881
    00882     Acl->AceCount = (USHORT)(Acl->AceCount + NewAceCount);
    00883
    00884     Acl->AclRevision = NewRevision;
    00885
    00886     //
    00887     //  And return to our caller
    00888     //
    00889
    00890     return STATUS_SUCCESS;
    00891 }
    00892
    00893
    00894 NTSTATUS
    00895 RtlDeleteAce (
    00896     IN OUT PACL Acl,
    00897     IN ULONG AceIndex
    00898     )
    00899
    00900 /*++
    00901
    00902 Routine Description:
    00903
    00904     This routine deletes one ACE from an ACL.
    00905
    00906 Arguments:
    00907
    00908     Acl - Supplies the Acl being modified
    00909
    00910     AceIndex - Supplies the index of the Ace to delete.
    00911
    00912 Return Value:
    00913
    00914     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
    00915         status otherwise
    00916
    00917 --*/
    00918
    00919 {
    00920     PVOID FirstFree;
    00921
    00922     PACE_HEADER Ace;
    00923     ULONG i;
    00924
    00925     RTL_PAGED_CODE();
    00926
    00927     //
    00928     //  Check the ACL structure
    00929     //
    00930
    00931     if (!RtlValidAcl(Acl)) {
    00932
    00933         return STATUS_INVALID_PARAMETER;
    00934
    00935     }
    00936
    00937     //
    00938     //  Make sure the AceIndex is within proper range, it's ulong so we know
    00939     //  it can't be negative
    00940     //
    00941
    00942     if (AceIndex >= Acl->AceCount) {
    00943
    00944         return STATUS_INVALID_PARAMETER;
    00945
    00946     }
    00947
    00948     //
    00949     //  Locate the first free spot, this will tell us how much data
    00950     //  we'll need to colapse.  If the results is false then the acl is
    00951     //  ill-formed
    00952     //
    00953
    00954     if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    00955
    00956         return STATUS_INVALID_PARAMETER;
    00957
    00958     }
    00959
    00960     //
    00961     //  Now locate the ace that we're going to delete.  This loop
    00962     //  doesn't need to check the acl for being well formed.
    00963     //
    00964
    00965     Ace = FirstAce( Acl );
    00966
    00967     for (i = 0; i < AceIndex; i++) {
    00968
    00969         Ace = NextAce( Ace );
    00970
    00971     }
    00972
    00973     //
    00974     //  We've found the ace to delete to simply copy over the rest of
    00975     //  the acl over this ace.  The delete data procedure also deletes
    00976     //  rest of the string that it's moving over so we don't have to
    00977     //
    00978
    00979     RtlpDeleteData( Ace, Ace->AceSize, (ULONG) ((PUCHAR)FirstFree - (PUCHAR)Ace));
    00980
    00981     //
    00982     //  Update the Acl header
    00983     //
    00984
    00985     Acl->AceCount--;
    00986
    00987     //
    00988     //  And return to our caller
    00989     //
    00990
    00991     return STATUS_SUCCESS;
    00992 }
    00993
    00994
    00995 NTSTATUS
    00996 RtlGetAce (
    00997     IN PACL Acl,
    00998     ULONG AceIndex,
    00999     OUT PVOID *Ace
    01000     )
    01001
    01002 /*++
    01003
    01004 Routine Description:
    01005
    01006     This routine returns a pointer to an ACE in an ACl referenced by
    01007     ACE index
    01008
    01009 Arguments:
    01010
    01011     Acl - Supplies the ACL being queried
    01012
    01013     AceIndex - Supplies the Ace index to locate
    01014
    01015     Ace - Receives the address of the ACE within the ACL
    01016
    01017 Return Value:
    01018
    01019     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
    01020         status otherwise
    01021
    01022 --*/
    01023
    01024 {
    01025     ULONG i;
    01026
    01027     RTL_PAGED_CODE();
    01028
    01029     //
    01030     //  Check the ACL revision level
    01031     //
    01032
    01033     if (!ValidAclRevision(Acl)) {
    01034
    01035         return STATUS_INVALID_PARAMETER;
    01036
    01037     }
    01038
    01039     //
    01040     //  Check the AceIndex against the Ace count of the Acl, it's ulong so
    01041     //  we know it can't be negative
    01042     //
    01043
    01044     if (AceIndex >= Acl->AceCount) {
    01045
    01046         return STATUS_INVALID_PARAMETER;
    01047
    01048     }
    01049
    01050     //
    01051     //  To find the Ace requested by zooming down the Ace List.
    01052     //
    01053
    01054     *Ace = FirstAce( Acl );
    01055
    01056     for (i = 0; i < AceIndex; i++) {
    01057
    01058         //
    01059         //  Check to make sure we haven't overrun the Acl buffer
    01060         //  with our ace pointer.  If we have then our input is bogus
    01061         //
    01062
    01063         if (*Ace >= (PVOID)((PUCHAR)Acl + Acl->AclSize)) {
    01064
    01065             return STATUS_INVALID_PARAMETER;
    01066
    01067         }
    01068
    01069         //
    01070         //  And move Ace to the next ace position
    01071         //
    01072
    01073         *Ace = NextAce( *Ace );
    01074
    01075     }
    01076
    01077     //
    01078     //  Now Ace points to the Ace we're after, but make sure we aren't
    01079     //  beyond the Acl.
    01080     //
    01081
    01082     if (*Ace >= (PVOID)((PUCHAR)Acl + Acl->AclSize)) {
    01083
    01084         return STATUS_INVALID_PARAMETER;
    01085
    01086     }
    01087
    01088     //
    01089     //  The Ace is still within the Acl so return success to our caller
    01090     //
    01091
    01092     return STATUS_SUCCESS;
    01093
    01094 }
    01095
    01096
    01097 NTSTATUS
    01098 RtlAddCompoundAce (
    01099     IN PACL Acl,
    01100     IN ULONG AceRevision,
    01101     IN UCHAR CompoundAceType,
    01102     IN ACCESS_MASK AccessMask,
    01103     IN PSID ServerSid,
    01104     IN PSID ClientSid
    01105     )
    01106
    01107 /*++
    01108
    01109 Routine Description:
    01110
    01111     This routine adds a KNOWN_COMPOUND_ACE to an ACL.  This is
    01112     expected to be a common form of ACL modification.
    01113
    01114 Arguments:
    01115
    01116     Acl - Supplies the Acl being modified
    01117
    01118     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01119
    01120     CompoundAceType - Supplies the type of compound ACE being added.
    01121         Currently the only defined type is COMPOUND_ACE_IMPERSONATION.
    01122
    01123     AccessMask - The mask of accesses to be granted to the specified SID pair.
    01124
    01125     ServerSid - Pointer to the Server SID to be placed in the ACE.
    01126
    01127     ClientSid - Pointer to the Client SID to be placed in the ACE.
    01128
    01129 Return Value:
    01130
    01131     NTSTATUS - STATUS_SUCCESS if successful and an appropriate error
    01132         status otherwise
    01133
    01134     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01135
    01136 --*/
    01137
    01138
    01139
    01140
    01141 {
    01142     PVOID FirstFree;
    01143     USHORT AceSize;
    01144     PKNOWN_COMPOUND_ACE GrantAce;
    01145     UCHAR NewRevision;
    01146
    01147     RTL_PAGED_CODE();
    01148
    01149     //
    01150     // Validate the structure of the SID
    01151     //
    01152
    01153     if (!RtlValidSid(ServerSid) || !RtlValidSid(ClientSid)) {
    01154         return STATUS_INVALID_SID;
    01155     }
    01156
    01157     //
    01158     //  Check the ACL & ACE revision levels
    01159     // Compund ACEs become valid in version 3.
    01160     //
    01161
    01162     if ( Acl->AclRevision > ACL_REVISION4 ||
    01163          AceRevision < ACL_REVISION3 ||
    01164          AceRevision > ACL_REVISION4 ) {
    01165         return STATUS_REVISION_MISMATCH;
    01166     }
    01167
    01168     //
    01169     // Calculate the new revision of the ACL.  The new revision is the maximum
    01170     // of the old revision and and new ACE's revision.  This is possible because
    01171     // the format of previously defined ACEs did not change across revisions.
    01172     //
    01173
    01174     NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
    01175
    01176     //
    01177     //  Locate the first free ace and check to see that the Acl is
    01178     //  well formed.
    01179     //
    01180
    01181     if (!RtlValidAcl( Acl )) {
    01182         return STATUS_INVALID_ACL;
    01183     }
    01184
    01185     if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    01186
    01187         return STATUS_INVALID_ACL;
    01188     }
    01189
    01190     //
    01191     //  Check to see if there is enough room in the Acl to store the new
    01192     //  ACE
    01193     //
    01194
    01195     AceSize = (USHORT)(sizeof(KNOWN_COMPOUND_ACE) -
    01196                        sizeof(ULONG)              +
    01197                        SeLengthSid(ClientSid)    +
    01198                        SeLengthSid(ServerSid)
    01199                        );
    01200
    01201     if (  FirstFree == NULL ||
    01202           ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
    01203        ) {
    01204
    01205         return STATUS_ALLOTTED_SPACE_EXCEEDED;
    01206     }
    01207
    01208     //
    01209     // Add the ACE to the end of the ACL
    01210     //
    01211
    01212     GrantAce = (PKNOWN_COMPOUND_ACE)FirstFree;
    01213     GrantAce->Header.AceFlags = 0;
    01214     GrantAce->Header.AceType = ACCESS_ALLOWED_COMPOUND_ACE_TYPE;
    01215     GrantAce->Header.AceSize = AceSize;
    01216     GrantAce->Mask = AccessMask;
    01217     GrantAce->CompoundAceType = CompoundAceType;
    01218     RtlCopySid( SeLengthSid(ServerSid), (PSID)(&GrantAce->SidStart), ServerSid );
    01219     RtlCopySid( SeLengthSid(ClientSid), (PSID)(((PCHAR)&GrantAce->SidStart) + SeLengthSid(ServerSid)), ClientSid );
    01220
    01221     //
    01222     // Increment the number of ACEs by 1.
    01223     //
    01224
    01225     Acl->AceCount += 1;
    01226
    01227     //
    01228     // Adjust the Acl revision, if necessary
    01229     //
    01230
    01231     Acl->AclRevision = NewRevision;
    01232
    01233     //
    01234     //  And return to our caller
    01235     //
    01236
    01237     return STATUS_SUCCESS;
    01238 }
    01239
    01240
    01241 NTSTATUS
    01242 RtlpAddKnownAce (
    01243     IN OUT PACL Acl,
    01244     IN ULONG AceRevision,
    01245     IN ULONG AceFlags,
    01246     IN ACCESS_MASK AccessMask,
    01247     IN PSID Sid,
    01248     IN UCHAR NewType
    01249     )
    01250
    01251 /*++
    01252
    01253 Routine Description:
    01254
    01255     This routine adds KNOWN_ACE to an ACL.  This is
    01256     expected to be a common form of ACL modification.
    01257
    01258     A very bland ACE header is placed in the ACE.  It provides no
    01259     inheritance and no ACE flags.  The type is specified by the caller.
    01260
    01261 Arguments:
    01262
    01263     Acl - Supplies the Acl being modified
    01264
    01265     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01266
    01267     AceFlags - Supplies the inherit flags for the ACE.
    01268
    01269     AccessMask - The mask of accesses to be denied to the specified SID.
    01270
    01271     Sid - Pointer to the SID being denied access.
    01272
    01273     NewType - Type of ACE to be added.
    01274
    01275 Return Value:
    01276
    01277     STATUS_SUCCESS - The ACE was successfully added.
    01278
    01279     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01280
    01281     STATUS_REVISION_MISMATCH - The specified revision is not known
    01282         or is incompatible with that of the ACL.
    01283
    01284     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01285         ACL.  A larger ACL buffer is required.
    01286
    01287     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01288         SID.
    01289
    01290     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01291
    01292 --*/
    01293
    01294 {
    01295     PVOID FirstFree;
    01296     USHORT AceSize;
    01297     PKNOWN_ACE GrantAce;
    01298     UCHAR NewRevision;
    01299     ULONG TestedAceFlags;
    01300
    01301     RTL_PAGED_CODE();
    01302
    01303     //
    01304     // Validate the structure of the SID
    01305     //
    01306
    01307     if (!RtlValidSid(Sid)) {
    01308         return STATUS_INVALID_SID;
    01309     }
    01310
    01311     //
    01312     //  Check the ACL & ACE revision levels
    01313     //
    01314
    01315     if ( Acl->AclRevision > ACL_REVISION4 || AceRevision > ACL_REVISION4 ) {
    01316
    01317         return STATUS_REVISION_MISMATCH;
    01318     }
    01319
    01320     //
    01321     // Calculate the new revision of the ACL.  The new revision is the maximum
    01322     // of the old revision and and new ACE's revision.  This is possible because
    01323     // the format of previously defined ACEs did not change across revisions.
    01324     //
    01325
    01326     NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
    01327
    01328     //
    01329     // Validate the AceFlags.
    01330     //
    01331
    01332     TestedAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
    01333     if ( TestedAceFlags != 0 ) {
    01334
    01335         if ( NewType == SYSTEM_AUDIT_ACE_TYPE ) {
    01336             TestedAceFlags &=
    01337                 ~(SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG);
    01338         }
    01339
    01340         if ( TestedAceFlags != 0 ) {
    01341             return STATUS_INVALID_PARAMETER;
    01342         }
    01343     }
    01344
    01345     //
    01346     //  Locate the first free ace and check to see that the Acl is
    01347     //  well formed.
    01348     //
    01349
    01350     if (!RtlValidAcl( Acl )) {
    01351         return STATUS_INVALID_ACL;
    01352     }
    01353     if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    01354
    01355         return STATUS_INVALID_ACL;
    01356     }
    01357
    01358     //
    01359     //  Check to see if there is enough room in the Acl to store the new
    01360     //  ACE
    01361     //
    01362
    01363     AceSize = (USHORT)(sizeof(ACE_HEADER) +
    01364                       sizeof(ACCESS_MASK) +
    01365                       SeLengthSid(Sid));
    01366
    01367     if (  FirstFree == NULL ||
    01368           ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
    01369        ) {
    01370
    01371         return STATUS_ALLOTTED_SPACE_EXCEEDED;
    01372     }
    01373
    01374     //
    01375     // Add the ACE to the end of the ACL
    01376     //
    01377
    01378     GrantAce = (PKNOWN_ACE)FirstFree;
    01379     GrantAce->Header.AceFlags = (UCHAR)AceFlags;
    01380     GrantAce->Header.AceType = NewType;
    01381     GrantAce->Header.AceSize = AceSize;
    01382     GrantAce->Mask = AccessMask;
    01383     RtlCopySid( SeLengthSid(Sid), (PSID)(&GrantAce->SidStart), Sid );
    01384
    01385     //
    01386     // Increment the number of ACEs by 1.
    01387     //
    01388
    01389     Acl->AceCount += 1;
    01390
    01391     //
    01392     // Adjust the Acl revision, if necessary
    01393     //
    01394
    01395     Acl->AclRevision = NewRevision;
    01396
    01397     //
    01398     //  And return to our caller
    01399     //
    01400
    01401     return STATUS_SUCCESS;
    01402 }
    01403
    01404 NTSTATUS
    01405 RtlpAddKnownObjectAce (
    01406     IN OUT PACL Acl,
    01407     IN ULONG AceRevision,
    01408     IN ULONG AceFlags,
    01409     IN ACCESS_MASK AccessMask,
    01410     IN GUID *ObjectTypeGuid OPTIONAL,
    01411     IN GUID *InheritedObjectTypeGuid OPTIONAL,
    01412     IN PSID Sid,
    01413     IN UCHAR NewType
    01414     )
    01415
    01416 /*++
    01417
    01418 Routine Description:
    01419
    01420     This routine adds KNOWN_ACE to an ACL.  This is
    01421     expected to be a common form of ACL modification.
    01422
    01423     A very bland ACE header is placed in the ACE.  It provides no
    01424     inheritance and no ACE flags.  The type is specified by the caller.
    01425
    01426 Arguments:
    01427
    01428     Acl - Supplies the Acl being modified
    01429
    01430     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01431
    01432     AceFlags - Supplies the inherit flags for the ACE.
    01433
    01434     AccessMask - The mask of accesses to be denied to the specified SID.
    01435
    01436     ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
    01437         If NULL, no object type GUID is placed in the ACE.
    01438
    01439     InheritedObjectTypeGuid - Supplies the GUID of the object type that will
    01440         inherit this ACE.  If NULL, no inherited object type GUID is placed in
    01441         the ACE.
    01442
    01443     Sid - Pointer to the SID being denied access.
    01444
    01445     NewType - Type of ACE to be added.
    01446
    01447 Return Value:
    01448
    01449     STATUS_SUCCESS - The ACE was successfully added.
    01450
    01451     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01452
    01453     STATUS_REVISION_MISMATCH - The specified revision is not known
    01454         or is incompatible with that of the ACL.
    01455
    01456     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01457         ACL.  A larger ACL buffer is required.
    01458
    01459     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01460         SID.
    01461
    01462     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01463
    01464 --*/
    01465
    01466 {
    01467     PVOID FirstFree;
    01468     USHORT AceSize;
    01469     PKNOWN_OBJECT_ACE GrantAce;
    01470     UCHAR NewRevision;
    01471     ULONG TestedAceFlags;
    01472     ULONG AceObjectFlags = 0;
    01473     ULONG SidSize;
    01474     PCHAR Where;
    01475
    01476     RTL_PAGED_CODE();
    01477
    01478     //
    01479     // Validate the structure of the SID
    01480     //
    01481
    01482     if (!RtlValidSid(Sid)) {
    01483         return STATUS_INVALID_SID;
    01484     }
    01485
    01486     //
    01487     //  Check the ACL & ACE revision levels
    01488     // Object ACEs became valid in version 4.
    01489     //
    01490
    01491     if ( Acl->AclRevision > ACL_REVISION4 || AceRevision != ACL_REVISION4 ) {
    01492
    01493         return STATUS_REVISION_MISMATCH;
    01494     }
    01495
    01496     //
    01497     // Calculate the new revision of the ACL.  The new revision is the maximum
    01498     // of the old revision and and new ACE's revision.  This is possible because
    01499     // the format of previously defined ACEs did not change across revisions.
    01500     //
    01501
    01502     NewRevision = Acl->AclRevision > (UCHAR)AceRevision ? Acl->AclRevision : (UCHAR)AceRevision;
    01503
    01504     //
    01505     // Validate the AceFlags.
    01506     //
    01507
    01508
    01509     TestedAceFlags = AceFlags & ~VALID_INHERIT_FLAGS;
    01510     if ( TestedAceFlags != 0 ) {
    01511
    01512         if ( NewType == SYSTEM_AUDIT_ACE_TYPE ||
    01513              NewType == SYSTEM_AUDIT_OBJECT_ACE_TYPE ) {
    01514             TestedAceFlags &=
    01515                 ~(SUCCESSFUL_ACCESS_ACE_FLAG|FAILED_ACCESS_ACE_FLAG);
    01516         }
    01517
    01518         if ( TestedAceFlags != 0 ) {
    01519             return STATUS_INVALID_PARAMETER;
    01520         }
    01521     }
    01522
    01523     //
    01524     //  Locate the first free ace and check to see that the Acl is
    01525     //  well formed.
    01526     //
    01527
    01528     if (!RtlValidAcl( Acl )) {
    01529         return STATUS_INVALID_ACL;
    01530     }
    01531     if (!RtlFirstFreeAce( Acl, &FirstFree )) {
    01532
    01533         return STATUS_INVALID_ACL;
    01534     }
    01535
    01536     //
    01537     //  Check to see if there is enough room in the Acl to store the new
    01538     //  ACE
    01539     //
    01540
    01541     SidSize = SeLengthSid(Sid);
    01542     AceSize = (USHORT)(sizeof(ACE_HEADER) +
    01543                       sizeof(ACCESS_MASK) +
    01544                       sizeof(ULONG) +
    01545                       SidSize);
    01546
    01547     if ( ARGUMENT_PRESENT(ObjectTypeGuid) ) {
    01548         AceObjectFlags |= ACE_OBJECT_TYPE_PRESENT;
    01549         AceSize += sizeof(GUID);
    01550     }
    01551
    01552     if ( ARGUMENT_PRESENT(InheritedObjectTypeGuid) ) {
    01553         AceObjectFlags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
    01554         AceSize += sizeof(GUID);
    01555     }
    01556
    01557     if (  FirstFree == NULL ||
    01558           ((PUCHAR)FirstFree + AceSize > ((PUCHAR)Acl + Acl->AclSize))
    01559        ) {
    01560
    01561         return STATUS_ALLOTTED_SPACE_EXCEEDED;
    01562     }
    01563
    01564     //
    01565     // Add the ACE to the end of the ACL
    01566     //
    01567
    01568     GrantAce = (PKNOWN_OBJECT_ACE)FirstFree;
    01569     GrantAce->Header.AceFlags = (UCHAR) AceFlags;
    01570     GrantAce->Header.AceType = NewType;
    01571     GrantAce->Header.AceSize = AceSize;
    01572     GrantAce->Mask = AccessMask;
    01573     GrantAce->Flags = AceObjectFlags;
    01574     Where = (PCHAR) (&GrantAce->SidStart);
    01575     if ( ARGUMENT_PRESENT(ObjectTypeGuid) ) {
    01576         RtlCopyMemory( Where, ObjectTypeGuid, sizeof(GUID) );
    01577         Where += sizeof(GUID);
    01578     }
    01579     if ( ARGUMENT_PRESENT(InheritedObjectTypeGuid) ) {
    01580         RtlCopyMemory( Where, InheritedObjectTypeGuid, sizeof(GUID) );
    01581         Where += sizeof(GUID);
    01582     }
    01583     RtlCopySid( SidSize, (PSID)Where, Sid );
    01584     Where += SidSize;
    01585
    01586     //
    01587     // Increment the number of ACEs by 1.
    01588     //
    01589
    01590     Acl->AceCount += 1;
    01591
    01592     //
    01593     // Adjust the Acl revision, if necessary
    01594     //
    01595
    01596     Acl->AclRevision = NewRevision;
    01597
    01598     //
    01599     //  And return to our caller
    01600     //
    01601
    01602     return STATUS_SUCCESS;
    01603 }
    01604
    01605
    01606 NTSTATUS
    01607 RtlAddAccessAllowedAce (
    01608     IN OUT PACL Acl,
    01609     IN ULONG AceRevision,
    01610     IN ACCESS_MASK AccessMask,
    01611     IN PSID Sid
    01612     )
    01613
    01614 /*++
    01615
    01616 Routine Description:
    01617
    01618     This routine adds an ACCESS_ALLOWED ACE to an ACL.  This is
    01619     expected to be a common form of ACL modification.
    01620
    01621     A very bland ACE header is placed in the ACE.  It provides no
    01622     inheritance and no ACE flags.
    01623
    01624 Arguments:
    01625
    01626     Acl - Supplies the Acl being modified
    01627
    01628     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01629
    01630     AccessMask - The mask of accesses to be granted to the specified SID.
    01631
    01632     Sid - Pointer to the SID being granted access.
    01633
    01634 Return Value:
    01635
    01636     STATUS_SUCCESS - The ACE was successfully added.
    01637
    01638     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01639
    01640     STATUS_REVISION_MISMATCH - The specified revision is not known
    01641         or is incompatible with that of the ACL.
    01642
    01643     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01644         ACL.  A larger ACL buffer is required.
    01645
    01646     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01647         SID.
    01648
    01649 --*/
    01650
    01651 {
    01652     RTL_PAGED_CODE();
    01653
    01654     return RtlpAddKnownAce (
    01655                Acl,
    01656                AceRevision,
    01657                0,   // No inherit flags
    01658                AccessMask,
    01659                Sid,
    01660                ACCESS_ALLOWED_ACE_TYPE
    01661                );
    01662 }
    01663
    01664
    01665 NTSTATUS
    01666 RtlAddAccessAllowedAceEx (
    01667     IN OUT PACL Acl,
    01668     IN ULONG AceRevision,
    01669     IN ULONG AceFlags,
    01670     IN ACCESS_MASK AccessMask,
    01671     IN PSID Sid
    01672     )
    01673
    01674 /*++
    01675
    01676 Routine Description:
    01677
    01678     This routine adds an ACCESS_ALLOWED ACE to an ACL.  This is
    01679     expected to be a common form of ACL modification.
    01680
    01681 Arguments:
    01682
    01683     Acl - Supplies the Acl being modified
    01684
    01685     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01686
    01687     AceFlags - Supplies the inherit flags for the ACE.
    01688
    01689     AccessMask - The mask of accesses to be granted to the specified SID.
    01690
    01691     Sid - Pointer to the SID being granted access.
    01692
    01693 Return Value:
    01694
    01695     STATUS_SUCCESS - The ACE was successfully added.
    01696
    01697     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01698
    01699     STATUS_REVISION_MISMATCH - The specified revision is not known
    01700         or is incompatible with that of the ACL.
    01701
    01702     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01703         ACL.  A larger ACL buffer is required.
    01704
    01705     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01706         SID.
    01707
    01708     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01709
    01710 --*/
    01711
    01712 {
    01713     RTL_PAGED_CODE();
    01714
    01715     return RtlpAddKnownAce (
    01716                Acl,
    01717                AceRevision,
    01718                AceFlags,
    01719                AccessMask,
    01720                Sid,
    01721                ACCESS_ALLOWED_ACE_TYPE
    01722                );
    01723 }
    01724
    01725
    01726 NTSTATUS
    01727 RtlAddAccessDeniedAce (
    01728     IN OUT PACL Acl,
    01729     IN ULONG AceRevision,
    01730     IN ACCESS_MASK AccessMask,
    01731     IN PSID Sid
    01732     )
    01733
    01734 /*++
    01735
    01736 Routine Description:
    01737
    01738     This routine adds an ACCESS_DENIED ACE to an ACL.  This is
    01739     expected to be a common form of ACL modification.
    01740
    01741     A very bland ACE header is placed in the ACE.  It provides no
    01742     inheritance and no ACE flags.
    01743
    01744 Arguments:
    01745
    01746     Acl - Supplies the Acl being modified
    01747
    01748     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01749
    01750     AccessMask - The mask of accesses to be denied to the specified SID.
    01751
    01752     Sid - Pointer to the SID being denied access.
    01753
    01754 Return Value:
    01755
    01756     STATUS_SUCCESS - The ACE was successfully added.
    01757
    01758     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01759
    01760     STATUS_REVISION_MISMATCH - The specified revision is not known
    01761         or is incompatible with that of the ACL.
    01762
    01763     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01764         ACL.  A larger ACL buffer is required.
    01765
    01766     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01767         SID.
    01768
    01769 --*/
    01770
    01771 {
    01772     RTL_PAGED_CODE();
    01773
    01774     return RtlpAddKnownAce (
    01775                Acl,
    01776                AceRevision,
    01777                0,   // No inherit flags
    01778                AccessMask,
    01779                Sid,
    01780                ACCESS_DENIED_ACE_TYPE
    01781                );
    01782
    01783 }
    01784
    01785
    01786 NTSTATUS
    01787 RtlAddAccessDeniedAceEx (
    01788     IN OUT PACL Acl,
    01789     IN ULONG AceRevision,
    01790     IN ULONG AceFlags,
    01791     IN ACCESS_MASK AccessMask,
    01792     IN PSID Sid
    01793     )
    01794
    01795 /*++
    01796
    01797 Routine Description:
    01798
    01799     This routine adds an ACCESS_DENIED ACE to an ACL.  This is
    01800     expected to be a common form of ACL modification.
    01801
    01802 Arguments:
    01803
    01804     Acl - Supplies the Acl being modified
    01805
    01806     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01807
    01808     AceFlags - Supplies the inherit flags for the ACE.
    01809
    01810     AccessMask - The mask of accesses to be denied to the specified SID.
    01811
    01812     Sid - Pointer to the SID being denied access.
    01813
    01814 Return Value:
    01815
    01816     STATUS_SUCCESS - The ACE was successfully added.
    01817
    01818     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01819
    01820     STATUS_REVISION_MISMATCH - The specified revision is not known
    01821         or is incompatible with that of the ACL.
    01822
    01823     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01824         ACL.  A larger ACL buffer is required.
    01825
    01826     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01827         SID.
    01828
    01829     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01830
    01831 --*/
    01832
    01833 {
    01834     RTL_PAGED_CODE();
    01835
    01836     return RtlpAddKnownAce (
    01837                Acl,
    01838                AceRevision,
    01839                AceFlags,
    01840                AccessMask,
    01841                Sid,
    01842                ACCESS_DENIED_ACE_TYPE
    01843                );
    01844
    01845 }
    01846
    01847
    01848 NTSTATUS
    01849 RtlAddAuditAccessAce (
    01850     IN OUT PACL Acl,
    01851     IN ULONG AceRevision,
    01852     IN ACCESS_MASK AccessMask,
    01853     IN PSID Sid,
    01854     IN BOOLEAN AuditSuccess,
    01855     IN BOOLEAN AuditFailure
    01856     )
    01857
    01858 /*++
    01859
    01860 Routine Description:
    01861
    01862     This routine adds a SYSTEM_AUDIT ACE to an ACL.  This is
    01863     expected to be a common form of ACL modification.
    01864
    01865     A very bland ACE header is placed in the ACE.  It provides no
    01866     inheritance.
    01867
    01868     Parameters are used to indicate whether auditing is to be performed
    01869     on success, failure, or both.
    01870
    01871 Arguments:
    01872
    01873     Acl - Supplies the Acl being modified
    01874
    01875     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01876
    01877     AccessMask - The mask of accesses to be denied to the specified SID.
    01878
    01879     Sid - Pointer to the SID to be audited.
    01880
    01881     AuditSuccess - If TRUE, indicates successful access attempts are to be
    01882         audited.
    01883
    01884     AuditFailure - If TRUE, indicated failed access attempts are to be
    01885         audited.
    01886
    01887 Return Value:
    01888
    01889     STATUS_SUCCESS - The ACE was successfully added.
    01890
    01891     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01892
    01893     STATUS_REVISION_MISMATCH - The specified revision is not known
    01894         or is incompatible with that of the ACL.
    01895
    01896     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01897         ACL.  A larger ACL buffer is required.
    01898
    01899     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01900         SID.
    01901
    01902 --*/
    01903
    01904 {
    01905     ULONG AceFlags = 0;
    01906     RTL_PAGED_CODE();
    01907
    01908     if (AuditSuccess) {
    01909         AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
    01910     }
    01911     if (AuditFailure) {
    01912         AceFlags |= FAILED_ACCESS_ACE_FLAG;
    01913     }
    01914
    01915     return RtlpAddKnownAce (
    01916                 Acl,
    01917                 AceRevision,
    01918                 AceFlags,
    01919                 AccessMask,
    01920                 Sid,
    01921                 SYSTEM_AUDIT_ACE_TYPE );
    01922
    01923 }
    01924
    01925 NTSTATUS
    01926 RtlAddAuditAccessAceEx (
    01927     IN OUT PACL Acl,
    01928     IN ULONG AceRevision,
    01929     IN ULONG AceFlags,
    01930     IN ACCESS_MASK AccessMask,
    01931     IN PSID Sid,
    01932     IN BOOLEAN AuditSuccess,
    01933     IN BOOLEAN AuditFailure
    01934     )
    01935
    01936 /*++
    01937
    01938 Routine Description:
    01939
    01940     This routine adds a SYSTEM_AUDIT ACE to an ACL.  This is
    01941     expected to be a common form of ACL modification.
    01942
    01943     A very bland ACE header is placed in the ACE.  It provides no
    01944     inheritance.
    01945
    01946     Parameters are used to indicate whether auditing is to be performed
    01947     on success, failure, or both.
    01948
    01949 Arguments:
    01950
    01951     Acl - Supplies the Acl being modified
    01952
    01953     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    01954
    01955     AceFlags - Supplies the inherit flags for the ACE.
    01956
    01957     AccessMask - The mask of accesses to be denied to the specified SID.
    01958
    01959     Sid - Pointer to the SID to be audited.
    01960
    01961     AuditSuccess - If TRUE, indicates successful access attempts are to be
    01962         audited.
    01963
    01964     AuditFailure - If TRUE, indicated failed access attempts are to be
    01965         audited.
    01966
    01967 Return Value:
    01968
    01969     STATUS_SUCCESS - The ACE was successfully added.
    01970
    01971     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    01972
    01973     STATUS_REVISION_MISMATCH - The specified revision is not known
    01974         or is incompatible with that of the ACL.
    01975
    01976     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    01977         ACL.  A larger ACL buffer is required.
    01978
    01979     STATUS_INVALID_SID - The provided SID is not a structurally valid
    01980         SID.
    01981
    01982     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    01983
    01984 --*/
    01985
    01986 {
    01987     RTL_PAGED_CODE();
    01988
    01989     if (AuditSuccess) {
    01990         AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
    01991     }
    01992     if (AuditFailure) {
    01993         AceFlags |= FAILED_ACCESS_ACE_FLAG;
    01994     }
    01995
    01996     return RtlpAddKnownAce (
    01997                 Acl,
    01998                 AceRevision,
    01999                 AceFlags,
    02000                 AccessMask,
    02001                 Sid,
    02002                 SYSTEM_AUDIT_ACE_TYPE );
    02003
    02004 }
    02005
    02006
    02007 NTSTATUS
    02008 RtlAddAccessAllowedObjectAce (
    02009     IN OUT PACL Acl,
    02010     IN ULONG AceRevision,
    02011     IN ULONG AceFlags,
    02012     IN ACCESS_MASK AccessMask,
    02013     IN GUID *ObjectTypeGuid OPTIONAL,
    02014     IN GUID *InheritedObjectTypeGuid OPTIONAL,
    02015     IN PSID Sid
    02016     )
    02017
    02018 /*++
    02019
    02020 Routine Description:
    02021
    02022     This routine adds an object specific ACCESS_ALLOWED ACE to an ACL.  This is
    02023     expected to be a common form of ACL modification.
    02024
    02025 Arguments:
    02026
    02027     Acl - Supplies the Acl being modified
    02028
    02029     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    02030
    02031     AceFlags - Supplies the inherit flags for the ACE.
    02032
    02033     AccessMask - The mask of accesses to be granted to the specified SID.
    02034
    02035     ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
    02036         If NULL, no object type GUID is placed in the ACE.
    02037
    02038     InheritedObjectTypeGuid - Supplies the GUID of the object type that will
    02039         inherit this ACE.  If NULL, no inherited object type GUID is placed in
    02040         the ACE.
    02041
    02042     Sid - Pointer to the SID being granted access.
    02043
    02044 Return Value:
    02045
    02046     STATUS_SUCCESS - The ACE was successfully added.
    02047
    02048     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    02049
    02050     STATUS_REVISION_MISMATCH - The specified revision is not known
    02051         or is incompatible with that of the ACL.
    02052
    02053     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    02054         ACL.  A larger ACL buffer is required.
    02055
    02056     STATUS_INVALID_SID - The provided SID is not a structurally valid
    02057         SID.
    02058
    02059     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    02060
    02061 --*/
    02062
    02063 {
    02064     RTL_PAGED_CODE();
    02065
    02066     //
    02067     // If no object types are specified,
    02068     //  build a non-object ACE.
    02069     //
    02070     if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
    02071         return RtlpAddKnownAce (
    02072                    Acl,
    02073                    AceRevision,
    02074                    AceFlags,
    02075                    AccessMask,
    02076                    Sid,
    02077                    ACCESS_ALLOWED_ACE_TYPE
    02078                    );
    02079     }
    02080
    02081     return RtlpAddKnownObjectAce (
    02082                Acl,
    02083                AceRevision,
    02084                AceFlags,
    02085                AccessMask,
    02086                ObjectTypeGuid,
    02087                InheritedObjectTypeGuid,
    02088                Sid,
    02089                ACCESS_ALLOWED_OBJECT_ACE_TYPE
    02090                );
    02091 }
    02092
    02093
    02094 NTSTATUS
    02095 RtlAddAccessDeniedObjectAce (
    02096     IN OUT PACL Acl,
    02097     IN ULONG AceRevision,
    02098     IN ULONG AceFlags,
    02099     IN ACCESS_MASK AccessMask,
    02100     IN GUID *ObjectTypeGuid OPTIONAL,
    02101     IN GUID *InheritedObjectTypeGuid OPTIONAL,
    02102     IN PSID Sid
    02103     )
    02104
    02105 /*++
    02106
    02107 Routine Description:
    02108
    02109     This routine adds an object specific ACCESS_DENIED ACE to an ACL.  This is
    02110     expected to be a common form of ACL modification.
    02111
    02112 Arguments:
    02113
    02114     Acl - Supplies the Acl being modified
    02115
    02116     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    02117
    02118     AceFlags - Supplies the inherit flags for the ACE.
    02119
    02120     AccessMask - The mask of accesses to be granted to the specified SID.
    02121
    02122     ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
    02123         If NULL, no object type GUID is placed in the ACE.
    02124
    02125     InheritedObjectTypeGuid - Supplies the GUID of the object type that will
    02126         inherit this ACE.  If NULL, no inherited object type GUID is placed in
    02127         the ACE.
    02128
    02129     Sid - Pointer to the SID being denied access.
    02130
    02131 Return Value:
    02132
    02133     STATUS_SUCCESS - The ACE was successfully added.
    02134
    02135     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    02136
    02137     STATUS_REVISION_MISMATCH - The specified revision is not known
    02138         or is incompatible with that of the ACL.
    02139
    02140     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    02141         ACL.  A larger ACL buffer is required.
    02142
    02143     STATUS_INVALID_SID - The provided SID is not a structurally valid
    02144         SID.
    02145
    02146     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    02147
    02148 --*/
    02149
    02150 {
    02151     RTL_PAGED_CODE();
    02152
    02153     //
    02154     // If no object types are specified,
    02155     //  build a non-object ACE.
    02156     //
    02157     if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
    02158         return RtlpAddKnownAce (
    02159                    Acl,
    02160                    AceRevision,
    02161                    AceFlags,
    02162                    AccessMask,
    02163                    Sid,
    02164                    ACCESS_DENIED_ACE_TYPE
    02165                    );
    02166     }
    02167
    02168     return RtlpAddKnownObjectAce (
    02169                Acl,
    02170                AceRevision,
    02171                AceFlags,
    02172                AccessMask,
    02173                ObjectTypeGuid,
    02174                InheritedObjectTypeGuid,
    02175                Sid,
    02176                ACCESS_DENIED_OBJECT_ACE_TYPE
    02177                );
    02178 }
    02179
    02180
    02181 NTSTATUS
    02182 RtlAddAuditAccessObjectAce (
    02183     IN OUT PACL Acl,
    02184     IN ULONG AceRevision,
    02185     IN ULONG AceFlags,
    02186     IN ACCESS_MASK AccessMask,
    02187     IN GUID *ObjectTypeGuid OPTIONAL,
    02188     IN GUID *InheritedObjectTypeGuid OPTIONAL,
    02189     IN PSID Sid,
    02190     IN BOOLEAN AuditSuccess,
    02191     IN BOOLEAN AuditFailure
    02192     )
    02193
    02194 /*++
    02195
    02196 Routine Description:
    02197
    02198     This routine adds an object specific ACCESS_DENIED ACE to an ACL.  This is
    02199     expected to be a common form of ACL modification.
    02200
    02201 Arguments:
    02202
    02203     Acl - Supplies the Acl being modified
    02204
    02205     AceRevision - Supplies the Acl/Ace revision of the ACE being added
    02206
    02207     AceFlags - Supplies the inherit flags for the ACE.
    02208
    02209     AccessMask - The mask of accesses to be granted to the specified SID.
    02210
    02211     ObjectTypeGuid - Supplies the GUID of the object this ACE applies to.
    02212         If NULL, no object type GUID is placed in the ACE.
    02213
    02214     InheritedObjectTypeGuid - Supplies the GUID of the object type that will
    02215         inherit this ACE.  If NULL, no inherited object type GUID is placed in
    02216         the ACE.
    02217
    02218     Sid - Pointer to the SID to be audited.
    02219
    02220     AuditSuccess - If TRUE, indicates successful access attempts are to be
    02221         audited.
    02222
    02223     AuditFailure - If TRUE, indicated failed access attempts are to be
    02224         audited.
    02225
    02226 Return Value:
    02227
    02228     STATUS_SUCCESS - The ACE was successfully added.
    02229
    02230     STATUS_INVALID_ACL - The specified ACL is not properly formed.
    02231
    02232     STATUS_REVISION_MISMATCH - The specified revision is not known
    02233         or is incompatible with that of the ACL.
    02234
    02235     STATUS_ALLOTTED_SPACE_EXCEEDED - The new ACE does not fit into the
    02236         ACL.  A larger ACL buffer is required.
    02237
    02238     STATUS_INVALID_SID - The provided SID is not a structurally valid
    02239         SID.
    02240
    02241     STATUS_INVALID_PARAMETER - The AceFlags parameter was invalid.
    02242
    02243 --*/
    02244
    02245 {
    02246     RTL_PAGED_CODE();
    02247
    02248     if (AuditSuccess) {
    02249         AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
    02250     }
    02251     if (AuditFailure) {
    02252         AceFlags |= FAILED_ACCESS_ACE_FLAG;
    02253     }
    02254
    02255     //
    02256     // If no object types are specified,
    02257     //  build a non-object ACE.
    02258     //
    02259     if (ObjectTypeGuid == NULL && InheritedObjectTypeGuid == NULL ) {
    02260         return RtlpAddKnownAce (
    02261                    Acl,
    02262                    AceRevision,
    02263                    AceFlags,
    02264                    AccessMask,
    02265                    Sid,
    02266                    SYSTEM_AUDIT_ACE_TYPE
    02267                    );
    02268     }
    02269
    02270     return RtlpAddKnownObjectAce (
    02271                Acl,
    02272                AceRevision,
    02273                AceFlags,
    02274                AccessMask,
    02275                ObjectTypeGuid,
    02276                InheritedObjectTypeGuid,
    02277                Sid,
    02278                SYSTEM_AUDIT_OBJECT_ACE_TYPE
    02279                );
    02280 }
    02281
    02282 #if 0
    02283
    02284 NTSTATUS
    02285 RtlMakePosixAcl(
    02286     IN ULONG AclRevision,
    02287     IN PSID UserSid,
    02288     IN PSID GroupSid,
    02289     IN ACCESS_MASK UserAccess,
    02290     IN ACCESS_MASK GroupAccess,
    02291     IN ACCESS_MASK OtherAccess,
    02292     IN ULONG AclLength,
    02293     OUT PACL Acl,
    02294     OUT PULONG ReturnLength
    02295     )
    02296 /*++
    02297
    02298 Routine Description:
    02299
    02300     NOTE: THIS ROUTINE IS STILL BEING SPEC'D.
    02301
    02302     Make an ACL representing Posix protection from AccessMask and
    02303     security account ID (SID) information.
    02304
    02305 Arguments:
    02306
    02307     AclRevision - Indicates the ACL revision level of the access masks
    02308         provided.  The ACL generated will be revision compatible with this
    02309         value and will not be a higher revision than this value.
    02310
    02311     UserSid - Provides the SID of the user (owner).
    02312
    02313     GroupSid - Provides the SID of the primary group.
    02314
    02315     UserAccess - Specifies the accesses to be given to the user (owner).
    02316
    02317     GroupAccess - Specifies the accesses to be given to the primary group.
    02318
    02319     OtherAccess - Specifies the accesses to be given to others (WORLD).
    02320
    02321     AclLength - Provides the length (in bytes) of the Acl buffer.
    02322
    02323     Acl - Points to a buffer to receive the generated ACL.
    02324
    02325     ReturnLength - Returns the actual length needed to store the resultant
    02326         ACL.  If this length is greater than that specified in AclLength,
    02327         then STATUS_BUFFER_TOO_SMALL is returned and no ACL is generated.
    02328
    02329 Return Values:
    02330
    02331     STATUS_SUCCESS - The service completed successfully.
    02332
    02333     STATUS_UNKNOWN_REVISION - The revision level specified is not supported
    02334         by this service.
    02335
    02336     STATUS_BUFFER_TOO_SMALL - Indicates the length of the output buffer
    02337         wasn't large enough to hold the generated ACL.  The length needed
    02338         is returned via the ReturnLength parameter.
    02339
    02340 --*/
    02341
    02342 {
    02343
    02344     SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
    02345
    02346     ULONG UserSidLength;
    02347     ULONG GroupSidLength;
    02348     ULONG WorldSidLength;
    02349     ULONG RequiredAclSize;
    02350     ULONG AceSize;
    02351     ULONG CurrentAce;
    02352     PACCESS_ALLOWED_ACE Ace;
    02353     NTSTATUS Status;
    02354
    02355     RTL_PAGED_CODE();
    02356
    02357     if (!RtlValidSid( UserSid ) || !RtlValidSid( GroupSid )) {
    02358         return( STATUS_INVALID_SID );
    02359     }
    02360
    02361     UserSidLength = SeLengthSid( UserSid );
    02362     GroupSidLength = SeLengthSid( GroupSid );
    02363     WorldSidLength = RtlLengthRequiredSid( 1 );
    02364
    02365     //
    02366     // Figure out how much room we need for an ACL and three
    02367     // ACCESS_ALLOWED Ace's
    02368     //
    02369
    02370     RequiredAclSize = sizeof( ACL );
    02371
    02372     AceSize = sizeof( ACCESS_ALLOWED_ACE ) - sizeof( ULONG );
    02373
    02374     RequiredAclSize += (AceSize * 3)  +
    02375                        UserSidLength  +
    02376                        GroupSidLength +
    02377                        WorldSidLength ;
    02378
    02379     if (RequiredAclSize > AclLength) {
    02380         *ReturnLength = RequiredAclSize;
    02381         return( STATUS_BUFFER_TOO_SMALL );
    02382     }
    02383
    02384     //
    02385     // The passed buffer is big enough, build the ACL in it.
    02386     //
    02387
    02388     Status = RtlCreateAcl(
    02389                  Acl,
    02390                  RequiredAclSize,
    02391                  AclRevision
    02392                  );
    02393
    02394     if (!NT_SUCCESS( Status )) {
    02395         return( Status );
    02396     }
    02397
    02398     CurrentAce = (ULONG)Acl + sizeof( ACL );
    02399     Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
    02400
    02401     //
    02402     // Build the user (owner) ACE
    02403     //
    02404
    02405     Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    02406     Ace->Header.AceSize = (USHORT)(UserSidLength + AceSize);
    02407     Ace->Header.AceFlags = 0;
    02408
    02409     Ace->Mask = UserAccess;
    02410
    02411     RtlMoveMemory(
    02412         (PVOID)(Ace->SidStart),
    02413         UserSid,
    02414         UserSidLength
    02415         );
    02416
    02417     CurrentAce += (ULONG)(Ace->Header.AceSize);
    02418     Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
    02419
    02420     //
    02421     // Build the group ACE
    02422     //
    02423
    02424     Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    02425     Ace->Header.AceSize = (USHORT)(GroupSidLength + AceSize);
    02426     Ace->Header.AceFlags = 0;
    02427
    02428     Ace->Mask = GroupAccess;
    02429
    02430     RtlMoveMemory(
    02431         (PVOID)(Ace->SidStart),
    02432         GroupSid,
    02433         GroupSidLength
    02434         );
    02435
    02436     CurrentAce += (ULONG)(Ace->Header.AceSize);
    02437     Ace = (PACCESS_ALLOWED_ACE)CurrentAce;
    02438
    02439     //
    02440     // Build the World ACE
    02441     //
    02442
    02443     Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
    02444     Ace->Header.AceSize = (USHORT)(GroupSidLength + AceSize);
    02445     Ace->Header.AceFlags = 0;
    02446
    02447     Ace->Mask = OtherAccess;
    02448
    02449     RtlInitializeSid(
    02450         (PSID)(Ace->SidStart),
    02451         &WorldSidAuthority,
    02452         1
    02453         );
    02454
    02455     *(RtlSubAuthoritySid((PSID)(Ace->SidStart), 0 )) = SECURITY_WORLD_RID;
    02456
    02457     return( STATUS_SUCCESS );
    02458
    02459 }
    02460
    02461 NTSTATUS
    02462 RtlInterpretPosixAcl(
    02463     IN ULONG AclRevision,
    02464     IN PSID UserSid,
    02465     IN PSID GroupSid,
    02466     IN PACL Acl,
    02467     OUT PACCESS_MASK UserAccess,
    02468     OUT PACCESS_MASK GroupAccess,
    02469     OUT PACCESS_MASK OtherAccess
    02470     )
    02471 /*++
    02472
    02473 Routine Description:
    02474
    02475     NOTE: THIS ROUTINE IS STILL BEING SPEC'D.
    02476
    02477     Interpret an ACL representing Posix protection, returning AccessMasks.
    02478     Use security account IDs (SIDs) for object owner and primary group
    02479     identification.
    02480
    02481     This algorithm will pick up the first match of a given SID and ignore
    02482     all further matches of that SID.  The first unrecognized SID becomes
    02483     the "other" SID.
    02484
    02485 Arguments:
    02486
    02487     AclRevision - Indicates the ACL revision level of the access masks to
    02488         be returned.
    02489
    02490     UserSid - Provides the SID of the user (owner).
    02491
    02492     GroupSid - Provides the SID of the primary group.
    02493
    02494     Acl - Points to a buffer containing the ACL to interpret.
    02495
    02496     UserAccess - Receives the accesses allowed for the user (owner).
    02497
    02498     GroupAccess - Receives the accesses allowed for the primary group.
    02499
    02500     OtherAccess - Receives the accesses allowed for others (WORLD).
    02501
    02502 Return Values:
    02503
    02504     STATUS_SUCCESS - The service completed successfully.
    02505
    02506     STATUS_UNKNOWN_REVISION - The revision level specified is not supported
    02507         by this service.
    02508
    02509     STATUS_EXTRENEOUS_INFORMATION - This warning status value indicates the
    02510         ACL contained protection or other information unrelated to Posix
    02511         style protection.  This is a warning only.  The interpretation was
    02512         otherwise successful and all access masks were returned.
    02513
    02514     STATUS_COULD_NOT_INTERPRET - Indicates the ACL does not contain
    02515         sufficient Posix style (user/group) protection information.  The
    02516         ACL could not be interpreted.
    02517
    02518 --*/
    02519 {
    02520     NTSTATUS Status = STATUS_SUCCESS;
    02521     BOOLEAN UserFound = FALSE;
    02522     BOOLEAN GroupFound = FALSE;
    02523     BOOLEAN OtherFound = FALSE;
    02524     ULONG i;
    02525     PKNOWN_ACE Ace;
    02526
    02527     RTL_PAGED_CODE();
    02528
    02529     if (AclRevision != ACL_REVISION2) {
    02530         return( STATUS_UNKNOWN_REVISION );
    02531     }
    02532
    02533     if (Acl->AceCount > 3) {
    02534         Status = STATUS_EXTRANEOUS_INFORMATION;
    02535     }
    02536
    02537     for (i=0, Ace = FirstAce( Acl );
    02538         (i < Acl->AceCount) && (!UserFound || !GroupFound || !OtherFound);
    02539         i++, Ace = NextAce( Ace )) {
    02540
    02541         if (Ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
    02542             Status = STATUS_EXTRANEOUS_INFORMATION;
    02543             continue;
    02544         }
    02545
    02546         if (RtlEqualSid(
    02547                (PSID)(Ace->SidStart),
    02548                UserSid
    02549                ) && !UserFound) {
    02550
    02551             *UserAccess = Ace->Mask;
    02552             UserFound = TRUE;
    02553             continue;
    02554         }
    02555
    02556         if (RtlEqualSid(
    02557                (PSID)(Ace->SidStart),
    02558                GroupSid
    02559                ) && !GroupFound) {
    02560
    02561             *GroupAccess = Ace->Mask;
    02562             GroupFound = TRUE;
    02563             continue;
    02564         }
    02565
    02566         //
    02567         // It isn't the user, and it isn't the group, pick it up
    02568         // as "other"
    02569         //
    02570
    02571         if (!OtherFound) {
    02572             *OtherAccess = Ace->Mask;
    02573             OtherFound = TRUE;
    02574             continue;
    02575         }
    02576
    02577     }
    02578
    02579     //
    02580     // Make sure we got everything we need, error otherwise
    02581     //
    02582
    02583     if (!UserFound || !GroupFound || !OtherFound) {
    02584         Status = STATUS_COULD_NOT_INTERPRET;
    02585     }
    02586
    02587     return( Status );
    02588
    02589 }
    02590
    02591 #endif // 0
    02592
    02593
    02594 //
    02595 //  Internal support routine
    02596 //
    02597
    02598 BOOLEAN
    02599 RtlFirstFreeAce (
    02600     IN PACL Acl,
    02601     OUT PVOID *FirstFree
    02602     )
    02603
    02604 /*++
    02605
    02606 Routine Description:
    02607
    02608     This routine returns a pointer to the first free byte in an Acl
    02609     or NULL if the acl is ill-formed.  If the Acl is full then the
    02610     return pointer is to the byte immediately following the acl, and
    02611     TRUE will be returned.
    02612
    02613 Arguments:
    02614
    02615     Acl - Supplies a pointer to the Acl to examine
    02616
    02617     FirstFree - Receives a pointer to the first free position in the Acl
    02618
    02619 Return Value:
    02620
    02621     BOOLEAN - TRUE if the Acl is well formed and FALSE otherwise
    02622
    02623 --*/
    02624
    02625 {
    02626     PACE_HEADER Ace;
    02627     ULONG i;
    02628
    02629     RTL_PAGED_CODE();
    02630
    02631     //
    02632     //  To find the first free spot in the Acl we need to search for
    02633     //  the last ace.  We do this by zooming down the list until
    02634     //  we've exhausted the ace count or the ace size (which ever comes
    02635     //  first).  In the following loop Ace points to the next spot
    02636     //  for an Ace and I is the ace index
    02637     //
    02638
    02639     *FirstFree = NULL;
    02640
    02641     for ( i=0, Ace = FirstAce( Acl );
    02642           i < Acl->AceCount;
    02643           i++, Ace = NextAce( Ace )) {
    02644
    02645         //
    02646         //  Check to make sure we haven't overrun the Acl buffer
    02647         //  with our Ace pointer.  If we have then our input is bogus.
    02648         //
    02649
    02650         if (Ace >= (PACE_HEADER)((PUCHAR)Acl + Acl->AclSize)) {
    02651
    02652             return FALSE;
    02653
    02654         }
    02655
    02656     }
    02657
    02658     //
    02659     //  Now Ace points to the first free spot in the Acl so set the
    02660     //  output variable and check to make sure it is still in the Acl
    02661     //  or just one beyond the end of the acl (i.e., the acl is full).
    02662     //
    02663
    02664     if (Ace <= (PACE_HEADER)((PUCHAR)Acl + Acl->AclSize)) {
    02665
    02666         *FirstFree = Ace;
    02667     }
    02668
    02669     //
    02670     //  The Acl is well formed so return the first free spot we've found
    02671     //  (or NULL if there is no free space for another ACE)
    02672     //
    02673
    02674     return TRUE;
    02675
    02676 }
    02677
    02678
    02679 //
    02680 //  Internal support routine
    02681 //
    02682
    02683 VOID
    02684 RtlpAddData (
    02685     IN PVOID From,
    02686     IN ULONG FromSize,
    02687     IN PVOID To,
    02688     IN ULONG ToSize
    02689     )
    02690
    02691 /*++
    02692
    02693 Routine Description:
    02694
    02695     This routine copies data to a string of bytes.  It does this by moving
    02696     over data in the to string so that the from string will fit.  It also
    02697     assumes that the checks that the data will fit in memory have already
    02698     been done.  Pictorally the results are as follows.
    02699
    02700     Before:
    02701
    02702         From -> ffffffffff
    02703
    02704         To   -> tttttttttttttttt
    02705
    02706     After:
    02707
    02708         From -> ffffffffff
    02709
    02710         To   -> fffffffffftttttttttttttttt
    02711
    02712 Arguments:
    02713
    02714     From - Supplies a pointer to the source buffer
    02715
    02716     FromSize - Supplies the size of the from buffer in bytes
    02717
    02718     To - Supplies a pointer to the destination buffer
    02719
    02720     ToSize - Supplies the size of the to buffer in bytes
    02721
    02722 Return Value:
    02723
    02724     None
    02725
    02726 --*/
    02727
    02728 {
    02729     LONG i;
    02730
    02731     //
    02732     //  Shift over the To buffer enough to fit in the From buffer
    02733     //
    02734
    02735     for (i = ToSize - 1; i >= 0; i--) {
    02736
    02737         ((PUCHAR)To)[i+FromSize] = ((PUCHAR)To)[i];
    02738     }
    02739
    02740     //
    02741     //  Now copy over the From buffer
    02742     //
    02743
    02744     for (i = 0; (ULONG)i < FromSize; i += 1) {
    02745
    02746         ((PUCHAR)To)[i] = ((PUCHAR)From)[i];
    02747
    02748     }
    02749
    02750     //
    02751     //  and return to our caller
    02752     //
    02753
    02754     return;
    02755
    02756 }
    02757
    02758
    02759 //
    02760 //  Internal support routine
    02761 //
    02762
    02763 VOID
    02764 RtlpDeleteData (
    02765     IN PVOID Data,
    02766     IN ULONG RemoveSize,
    02767     IN ULONG TotalSize
    02768     )
    02769
    02770 /*++
    02771
    02772 Routine Description:
    02773
    02774     This routine deletes a string of bytes from the front of a data buffer
    02775     and compresses the data.  It also zeros out the part of the string
    02776     that is no longer in use.  Pictorially the results are as follows
    02777
    02778     Before:
    02779
    02780         Data       = DDDDDddddd
    02781         RemoveSize = 5
    02782         TotalSize  = 10
    02783
    02784     After:
    02785
    02786         Data      = ddddd00000
    02787
    02788 Arguments:
    02789
    02790     Data - Supplies a pointer to the data being altered
    02791
    02792     RemoveSize - Supplies the number of bytes to delete from the front
    02793         of the data buffer
    02794
    02795     TotalSize - Supplies the total number of bytes in the data buffer
    02796         before the delete operation
    02797
    02798 Return Value:
    02799
    02800     None
    02801
    02802 --*/
    02803
    02804 {
    02805     ULONG i;
    02806
    02807     //
    02808     //  Shift over the buffer to remove the amount
    02809     //
    02810
    02811     for (i = RemoveSize; i < TotalSize; i++) {
    02812
    02813         ((PUCHAR)Data)[i-RemoveSize] = ((PUCHAR)Data)[i];
    02814
    02815     }
    02816
    02817     //
    02818     //  Now as a safety precaution we'll zero out the rest of the string
    02819     //
    02820
    02821     for (i = TotalSize - RemoveSize; i < TotalSize; i++) {
    02822
    02823         ((PUCHAR)Data)[i] = 0;
    02824     }
    02825
    02826     //
    02827     //  And return to our caller
    02828     //
    02829
    02830     return;
    02831
    02832 }