Browse Source

Merge pull request #101 from raandree/ai/defects-b

fix: ignored parameters and parameter sets (defect group B)
pull/112/head
Raimund Andrée 6 days ago
committed by GitHub
parent
commit
04bbd50ace
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      .memory-bank/activeContext.md
  2. 4
      .memory-bank/progress.md
  3. 20
      CHANGELOG.md
  4. 12
      Docs/Cmdlets/Add-NTFSAccess.md
  5. 12
      Docs/Cmdlets/Add-NTFSAudit.md
  6. 10
      Docs/Cmdlets/Get-NTFSEffectiveAccess.md
  7. 12
      Docs/Cmdlets/Get-NTFSOrphanedAccess.md
  8. 14
      Docs/Cmdlets/Get-NTFSOrphanedAudit.md
  9. 14
      Docs/Cmdlets/Get-NTFSSimpleAccess.md
  10. 34
      Docs/Cmdlets/Remove-NTFSAccess.md
  11. 40
      Docs/Cmdlets/Remove-NTFSAudit.md
  12. 8
      Docs/Concepts.md
  13. 5
      NTFSSecurity/AccessCmdlets/AddAccess.cs
  14. 123
      NTFSSecurity/AccessCmdlets/GetEffectiveAccess.cs
  15. 44
      NTFSSecurity/AccessCmdlets/GetOrphanedAccess.cs
  16. 23
      NTFSSecurity/AccessCmdlets/RemoveAccess.cs
  17. 5
      NTFSSecurity/AuditCmdlets/AddAudit.cs
  18. 52
      NTFSSecurity/AuditCmdlets/Get-OrphanedAudit.cs
  19. 23
      NTFSSecurity/AuditCmdlets/RemoveAudit.cs
  20. 50
      NTFSSecurity/NTFSSecurity.format.ps1xml
  21. 19
      NTFSSecurity/SimpleAccessCmdlets/SimpleAccessCmdlets.cs
  22. 260
      NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
  23. 11
      Security2/EffectiveAccess.cs
  24. 2
      Security2/FileSystem/FileSystemAccessRule2 Class/FileSystemAccessRule2.RemoveFileSystemAccessRules.cs
  25. 22
      Security2/FileSystem/FileSystemAuditRule2 Class/FileSystemAuditRule2.RemoveFileSystemAuditRule.cs
  26. 183
      Tests/Access.Tests.ps1
  27. 49
      Tests/Audit.Tests.ps1

5
.memory-bank/activeContext.md

@ -45,8 +45,11 @@ the PRs, and tags `5.0.0-rc2` after the merges.
`Get-NTFSAccess` (found with 4): Windows PowerShell 310 passed, 17
skipped; PowerShell 7 280 passed, 47 skipped (327 tests). 10 tests need
privileges and run only in CI.
- `ai/defects-b` fixes defects 14 to 17 (`-AppliesTo` is mandatory in the
`Simple` sets; `-RemoveSpecific` is back): Windows PowerShell 331 passed,
19 skipped; PowerShell 7 301 passed, 49 skipped (350 tests).
## Next step
Group B (14 to 17) on `ai/defects-b`, then C, D, the E decisions, and the
Group C (18 to 21) on `ai/defects-c`, then D, the E decisions, and the
bugs from the issue triage (`ai/issue-fixes`).

4
.memory-bank/progress.md

@ -125,7 +125,7 @@ Numbered as agreed with the maintainer; each is documented on its page.
- Review of group A: five Major findings fixed in the last commit; the
Minor ones are listed in the PR description.
#### B: Ignored parameters and parameter sets
#### B: Ignored parameters and parameter sets (fixed on `ai/defects-b`, not merged)
- (14) SD sets of `Add-/Remove-NTFSAccess` and `Add-/Remove-NTFSAudit`
cannot resolve without `-AppliesTo` or the flag parameters.
@ -138,6 +138,8 @@ Numbered as agreed with the maintainer; each is documented on its page.
has no format view.
- (17) `removeSpecific` in `Remove-NTFSAccess/Audit` is never bound;
`Remove-NTFSAudit` leaves `appliesTo` uninitialized.
- Review of group B: no Blocker or Major; three Minor findings fixed, the
rest are listed in the PR description.
#### C: Error handling

20
CHANGELOG.md

@ -92,5 +92,25 @@ The format is based on
`EnablePrivileges` was `$false`, and left them enabled
- Fix the `Inherits` column of the `Get-ChildItem2` output, which showed
`True` for every item, also for items whose inheritance is disabled
- Fix `Add-NTFSAccess`, `Remove-NTFSAccess`, `Add-NTFSAudit`, and
`Remove-NTFSAudit`, which failed with "Parameter set cannot be resolved"
for `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or
`-PropagationFlags`; `-AppliesTo` is now mandatory in the `Simple`
parameter sets, so such a command uses the flag parameters and their
defaults, as for a path
- Fix `Get-NTFSEffectiveAccess`: `-ExcludeNoneAccessEntries` now leaves out
items without access, the cmdlet uses the current location when `-Path`
is omitted, and `-SecurityDescriptor` returns the effective access of the
security descriptor; before, all three returned nothing or ignored the
parameter
- Fix `Get-NTFSOrphanedAccess`, `Get-NTFSOrphanedAudit`, and
`Get-NTFSSimpleAccess`, which ignored `-Account` and `-SecurityDescriptor`;
`Get-NTFSOrphanedAudit` now writes one object per entry instead of one
collection per item, `Get-NTFSOrphanedAccess` no longer repeats the entries
of the previous item after a failed read, and the output of
`Get-NTFSSimpleAccess` has a table view
- Restore the `-RemoveSpecific` switch of `Remove-NTFSAccess`, which version
4.1 introduced but later versions lacked, and add it to `Remove-NTFSAudit`:
with it, the cmdlets remove only an entry that matches exactly
[Unreleased]: https://github.com/raandree/NTFSSecurity/compare/4.2.6...HEAD

12
Docs/Cmdlets/Add-NTFSAccess.md

@ -23,13 +23,13 @@ Add-NTFSAccess [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRigh
### PathSimple
```
Add-NTFSAccess [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AccessType <AccessControlType>] [-AppliesTo <ApplyTo>] [-PassThru] [<CommonParameters>]
[-AccessType <AccessControlType>] -AppliesTo <ApplyTo> [-PassThru] [<CommonParameters>]
```
### SDSimple
```
Add-NTFSAccess [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AccessType <AccessControlType>] [-AppliesTo <ApplyTo>] [-PassThru]
[-AccessRights] <FileSystemRights2> [-AccessType <AccessControlType>] -AppliesTo <ApplyTo> [-PassThru]
[<CommonParameters>]
```
@ -46,7 +46,7 @@ Adds an access control entry (ACE) to the discretionary access control list (DAC
`-AccessRights` accepts the basic rights such as `Read`, `Modify`, and `FullControl` as well as the granular rights such as `CreateFiles` or `WriteAttributes`, and several values can be combined, for example `-AccessRights ReadData, WriteData, Delete`. For the mapping between the values of this module, the rights that Windows displays, and the entries of the advanced security dialog, see [Concepts](../Concepts.md).
The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`; both describe the same ACE flags, and `PathComplex` is the default. A command that works on a security descriptor, whether it is passed to `-SecurityDescriptor` or piped in, must therefore name `-AppliesTo` or `-InheritanceFlags` and `-PropagationFlags`; without one of them PowerShell cannot choose between the two `SD` sets and reports that the parameter set cannot be resolved.
The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`; both describe the same ACE flags, and `PathComplex` is the default. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.
When `-AccessType`, `-AppliesTo`, `-InheritanceFlags`, and `-PropagationFlags` are omitted, the cmdlet adds an `Allow` ACE that applies to this folder, subfolders, and files, which corresponds to the inheritance flags `ContainerInherit, ObjectInherit` and no propagation flags. An `Allow` ACE always receives the `Synchronize` right in addition to the requested rights, inheritance and propagation flags are ignored on files, and rights for an account that already has an ACE with the same access type and the same flags are merged into that ACE. The cmdlet writes no output unless `-PassThru` is used, and a failure on one item is reported as a non-terminating error while the remaining items are processed.
@ -140,7 +140,7 @@ Accept wildcard characters: False
### -AppliesTo
Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The default is `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.
Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.
```yaml
Type: ApplyTo
@ -148,9 +148,9 @@ Parameter Sets: PathSimple, SDSimple
Aliases:
Accepted values: ThisFolderOnly, ThisFolderSubfoldersAndFiles, ThisFolderAndSubfolders, ThisFolderAndFiles, SubfoldersAndFilesOnly, SubfoldersOnly, FilesOnly, ThisFolderSubfoldersAndFilesOneLevel, ThisFolderAndSubfoldersOneLevel, ThisFolderAndFilesOneLevel, SubfoldersAndFilesOnlyOneLevel, SubfoldersOnlyOneLevel, FilesOnlyOneLevel
Required: False
Required: True
Position: Named
Default value: ThisFolderSubfoldersAndFiles
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```

12
Docs/Cmdlets/Add-NTFSAudit.md

@ -23,13 +23,13 @@ Add-NTFSAudit [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRight
### PathSimple
```
Add-NTFSAudit [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AuditFlags <AuditFlags>] [-AppliesTo <ApplyTo>] [-PassThru] [<CommonParameters>]
[-AuditFlags <AuditFlags>] -AppliesTo <ApplyTo> [-PassThru] [<CommonParameters>]
```
### SDSimple
```
Add-NTFSAudit [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AuditFlags <AuditFlags>] [-AppliesTo <ApplyTo>] [-PassThru]
[-AccessRights] <FileSystemRights2> [-AuditFlags <AuditFlags>] -AppliesTo <ApplyTo> [-PassThru]
[<CommonParameters>]
```
@ -46,7 +46,7 @@ The `Add-NTFSAudit` cmdlet adds an audit entry to the system access control list
In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path`, adds the entry, and writes the descriptor back right away. In the `SDSimple` and `SDComplex` parameter sets it adds the entry to an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned; that change only reaches the file system when you pass the object to `Set-NTFSSecurityDescriptor`. The simple sets describe the scope of the entry with the single `-AppliesTo` parameter, the complex sets with `-InheritanceFlags` and `-PropagationFlags`.
`PathComplex` is the default parameter set. Because that set requires `-Path`, a command that uses `-SecurityDescriptor` must also specify `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags`; otherwise PowerShell cannot decide between `SDSimple` and `SDComplex` and reports that the parameter set cannot be resolved.
`PathComplex` is the default parameter set. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.
When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`, and `-AppliesTo` is `ThisFolderSubfoldersAndFiles`, so both the simple and the complex set audit the item, its subfolders, and its files by default. Inheritance applies to folders only: when the item is a file, the cmdlet stores the entry without inheritance and propagation flags.
@ -125,7 +125,7 @@ Accept wildcard characters: False
### -AppliesTo
Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. The default is `ThisFolderSubfoldersAndFiles`.
Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.
```yaml
Type: ApplyTo
@ -133,9 +133,9 @@ Parameter Sets: PathSimple, SDSimple
Aliases:
Accepted values: ThisFolderOnly, ThisFolderSubfoldersAndFiles, ThisFolderAndSubfolders, ThisFolderAndFiles, SubfoldersAndFilesOnly, SubfoldersOnly, FilesOnly, ThisFolderSubfoldersAndFilesOneLevel, ThisFolderAndSubfoldersOneLevel, ThisFolderAndFilesOneLevel, SubfoldersAndFilesOnlyOneLevel, SubfoldersOnlyOneLevel, FilesOnlyOneLevel
Required: False
Required: True
Position: Named
Default value: ThisFolderSubfoldersAndFiles
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```

10
Docs/Cmdlets/Get-NTFSEffectiveAccess.md

@ -33,7 +33,7 @@ The calculation covers the NTFS permissions of the item only. Share permissions
When `-Account` is omitted, the account that runs the session is used. `-ServerName` selects the computer whose authorization manager resolves the group memberships of the account and defaults to `localhost`; when the remote authorization manager of the named computer cannot be reached, the cmdlet falls back to the local one and warns that the result is based on the group memberships known on this computer and may be inaccurate. Reading effective access relies on the Security privilege, and the cmdlet warns when the account does not hold it or the privilege is disabled.
Although `-Path` is optional, the cmdlet writes nothing when the parameter is omitted; pass a path or pipe items in. The `SecurityDescriptor` parameter set is accepted by the parameter binder but produces no output, so use `-Path` to query effective access.
When `-Path` is omitted, the cmdlet calculates the effective access to the current location. In the `SecurityDescriptor` parameter set, it calculates the effective access from a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, without reading the item again.
## EXAMPLES
@ -89,7 +89,7 @@ Accept wildcard characters: False
### -ExcludeNoneAccessEntries
Indicates that items on which the account has no rights at all are left out of the result. In this release the switch does not suppress anything: the cmdlet writes a result for every item it processes, even when the calculated access mask is `None`.
Indicates that items on which the account has no rights at all are left out of the result. Because every calculated result includes the `Synchronize` right, an item counts as without rights when `Synchronize` is the only right.
```yaml
Type: SwitchParameter
@ -105,7 +105,7 @@ Accept wildcard characters: False
### -Path
Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. The cmdlet writes nothing when no path is supplied.
Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. When you omit the parameter, the cmdlet uses the current location.
```yaml
Type: String[]
@ -121,7 +121,7 @@ Accept wildcard characters: False
### -SecurityDescriptor
This parameter is accepted by the parameter binder but has no effect. The cmdlet produces no output in this parameter set; use `-Path` instead.
Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet calculates the effective access from the in-memory object instead of reading the item again.
A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.
@ -182,6 +182,8 @@ When the module setting `EnablePrivileges` is `$true` (the default in the `Priva
Reading effective access needs the Security privilege. In a session that does not hold it, the cmdlet warns before it starts and the calculation may fail with an error. Use `Enable-Privileges` in an elevated session to enable the privilege, and `Get-Privileges` to see which privileges the session holds.
Before 5.0.0, `-ExcludeNoneAccessEntries` had no effect, and the cmdlet returned nothing without `-Path` or for `-SecurityDescriptor`.
## RELATED LINKS
[Get-NTFSAccess](Get-NTFSAccess.md)

12
Docs/Cmdlets/Get-NTFSOrphanedAccess.md

@ -33,7 +33,7 @@ An entry counts as orphaned only as long as the name resolution fails, and the c
Relative paths are resolved against the current location, and the current location is searched when `-Path` is omitted. By default both explicit and inherited entries are returned, which means that the same orphaned entry appears on every item that inherits it; `-ExcludeInherited` reports it only on the item where it is defined. With `-Verbose`, the cmdlet reports the number of orphaned entries per item and the total at the end.
The `-Account` and `-SecurityDescriptor` parameters are inherited from `Get-NTFSAccess` and have no effect on this cmdlet. Entries are never filtered by account, and a security descriptor passed to `-SecurityDescriptor` is ignored; the cmdlet reads the current location instead.
`-Account` limits the result to the entries of one account, which you specify by its SID. With `-SecurityDescriptor`, the cmdlet examines a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned instead of reading the item again.
## EXAMPLES
@ -65,7 +65,7 @@ This command deletes the orphaned entries from the items they are defined on. Th
### -Account
This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts that cannot be resolved.
Specifies the account whose orphaned entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.
```yaml
Type: IdentityReference2
@ -129,7 +129,7 @@ Accept wildcard characters: False
### -SecurityDescriptor
This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet searches the path in `-Path` or the current location instead.
Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.
A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.
@ -156,11 +156,11 @@ One or more paths of files or folders, piped by value or by the property `FullNa
### Security2.FileSystemSecurity2[]
Security descriptors are accepted by the parameter binder but ignored by this cmdlet.
You can pipe the security descriptors that `Get-NTFSSecurityDescriptor` returns to this cmdlet.
### Security2.IdentityReference2
An account is accepted by the parameter binder but ignored by this cmdlet.
An account name or a SID string binds to `-Account`.
## OUTPUTS
@ -174,6 +174,8 @@ When the module setting `EnablePrivileges` is `$true` (the default in the `Priva
If the ACL of an item cannot be read because access is denied, the cmdlet tries once more after making the current account the owner of the item, and restores the previous owner afterwards. Changing the owner of an item requires the Take Ownership and Restore privileges, so this fallback only succeeds in an elevated session of an account that holds them.
Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor`, and after a path whose ACL could not be read, it returned the orphaned entries of the previous item again.
## RELATED LINKS
[Get-NTFSAccess](Get-NTFSAccess.md)

14
Docs/Cmdlets/Get-NTFSOrphanedAudit.md

@ -33,7 +33,7 @@ An entry is reported as orphaned whenever the name resolution fails at that mome
The cmdlet is built on `Get-NTFSAudit` and reads the SACL of every item in `-Path`, using the current location when you omit the parameter. `-Path` accepts pipeline input by value and by property name through its `FullName` alias, so the output of `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` binds to it. `-ExcludeExplicit` and `-ExcludeInherited` narrow the entries that are examined, and `-Verbose` reports how many orphaned entries each item has and their total.
`Get-NTFSOrphanedAudit` inherits the `-Account` and `-SecurityDescriptor` parameters from `Get-NTFSAudit`, but it does not evaluate them. The entries are always read from the items in `-Path`, so a command that passes `-SecurityDescriptor` examines the current location instead of the descriptor.
`-Account` limits the result to the entries of one account, which you specify by its SID. With `-SecurityDescriptor`, the cmdlet examines a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned; a descriptor that was read without the Security privilege doesn't contain the audit entries, and the cmdlet writes an error for it.
## EXAMPLES
@ -60,7 +60,7 @@ PS C:\> $orphaned = Get-NTFSOrphanedAudit -Path C:\Data -Verbose
PS C:\> $orphaned | Select-Object FullName, Account, AccessRights, AuditFlags
```
This command stores the result in a variable and then lists the item, the unresolved SID, the audited rights, and the audit flags of every orphaned entry. Storing the result first is necessary because the cmdlet writes one collection per item rather than one object per entry.
This command stores the result in a variable and then lists the item, the unresolved SID, the audited rights, and the audit flags of every orphaned entry.
### Example 4: Check the current location
@ -74,7 +74,7 @@ This command examines the current location, because `-Path` is omitted.
### -Account
Specifies an account in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not evaluate it, so the result always contains the entries of every account whose SID cannot be resolved.
Specifies the account whose orphaned audit entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.
```yaml
Type: IdentityReference2
@ -138,7 +138,7 @@ Accept wildcard characters: False
### -SecurityDescriptor
Specifies one or more security descriptors in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not read from it; the cmdlet always examines the items in `-Path` and therefore the current location when `-Path` is omitted. Use `Get-NTFSAudit -SecurityDescriptor` to inspect the audit entries of a security descriptor.
Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.
```yaml
Type: FileSystemSecurity2[]
@ -167,13 +167,13 @@ Security descriptors bind to the inherited `-SecurityDescriptor` parameter, but
### Security2.IdentityReference2
An account name or a SID string binds to the inherited `-Account` parameter, which this cmdlet does not evaluate.
An account name or a SID string binds to `-Account`.
## OUTPUTS
### Security2.FileSystemAuditRule2
The cmdlet returns the audit entries whose account SID cannot be translated into a name, each with the item, the unresolved account, the audited access rights, the audit flags, and the inheritance information. The entries of an item are written as a single collection rather than one object per entry, so store the result in a variable before you filter or format it; an item without orphaned entries still produces one empty collection, and a command placed directly after this cmdlet in the pipeline receives the collection instead of the individual entries.
The cmdlet returns the audit entries whose account SID cannot be translated into a name, each with the item, the unresolved account, the audited access rights, the audit flags, and the inheritance information. The cmdlet writes one object per entry.
## NOTES
@ -183,6 +183,8 @@ Reading the SACL requires the Security privilege (`SeSecurityPrivilege`, "Manage
If an item cannot be read, the cmdlet writes a warning and continues with the next item. Unlike `Get-NTFSAudit`, it does not try to take ownership of the item when access is denied.
Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor` and wrote the entries of each item as one collection.
## RELATED LINKS
[Get-NTFSAudit](Get-NTFSAudit.md)

14
Docs/Cmdlets/Get-NTFSSimpleAccess.md

@ -33,7 +33,7 @@ The second simplification is that repetitions are left out. The first folder the
`-IncludeRootFolder` is on by default and adds the parent folder of the first path as the baseline for the comparison, which is why the first result usually belongs to the folder above the one that was asked for. Use `-IncludeRootFolder:$false` to start the comparison at the first path itself.
The cmdlet only processes folders; a path that points to a file is skipped silently. Relative paths are resolved against the current location, and the current location is used when `-Path` is omitted. `-ExcludeInherited` and `-ExcludeExplicit` work as in `Get-NTFSAccess`, while `-Account` and `-SecurityDescriptor` are inherited from that cmdlet and have no effect here.
The cmdlet only processes folders; a path that points to a file is skipped silently, while the security descriptor of a file is reported. Relative paths are resolved against the current location, and the current location is used when `-Path` is omitted. `-ExcludeInherited`, `-ExcludeExplicit`, and `-Account` work as in `Get-NTFSAccess`. With `-SecurityDescriptor`, the cmdlet reports the entries of a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, without comparing them with a parent folder.
## EXAMPLES
@ -65,7 +65,7 @@ This command shows the explicit entries of `C:\Data` in simplified form and leav
### -Account
This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts.
Specifies the account whose entries are returned. When you omit the parameter, the cmdlet returns the entries of all accounts.
```yaml
Type: IdentityReference2
@ -145,7 +145,7 @@ Accept wildcard characters: False
### -SecurityDescriptor
This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet reads the path in `-Path` or the current location instead.
Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet reports the entries of the in-memory objects instead of reading the items again.
A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.
@ -172,17 +172,17 @@ One or more paths of folders, piped by value or by the property `FullName`.
### Security2.FileSystemSecurity2[]
Security descriptors are accepted by the parameter binder but ignored by this cmdlet.
You can pipe the security descriptors that `Get-NTFSSecurityDescriptor` returns to this cmdlet.
### Security2.IdentityReference2
An account is accepted by the parameter binder but ignored by this cmdlet.
An account name or a SID string binds to `-Account`.
## OUTPUTS
### Security2.SimpleFileSystemAccessRule
One object per reported entry, with the folder in `FullName` and `Name`, the account in `Identity`, the access type in `AccessControlType`, and the simplified rights `Read`, `Write`, and `Delete` in `AccessRights`.
One object per reported entry, with the folder in `FullName` and `Name`, the account in `Identity`, the access type in `AccessControlType`, and the simplified rights `Read`, `Write`, and `Delete` in `AccessRights`. The default view is a table with the `Account`, `Access Rights`, and `Type` columns, grouped by folder.
## NOTES
@ -190,6 +190,8 @@ When the module setting `EnablePrivileges` is `$true` (the default in the `Priva
The simplified rights hide which exact rights an account holds. Use `Get-NTFSAccess` when you need the full access control entry, and `Get-NTFSEffectiveAccess` when you need the rights that result from all entries together.
Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor`, and its output had no table view.
## RELATED LINKS
[Get-NTFSAccess](Get-NTFSAccess.md)

34
Docs/Cmdlets/Remove-NTFSAccess.md

@ -17,38 +17,38 @@ Removes rights from the access control entries (ACEs) of a file, a folder, or a
```
Remove-NTFSAccess [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AccessType <AccessControlType>] [-InheritanceFlags <InheritanceFlags>]
[-PropagationFlags <PropagationFlags>] [-PassThru] [<CommonParameters>]
[-PropagationFlags <PropagationFlags>] [-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
### PathSimple
```
Remove-NTFSAccess [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AccessType <AccessControlType>] [-AppliesTo <ApplyTo>] [-PassThru] [<CommonParameters>]
[-AccessType <AccessControlType>] -AppliesTo <ApplyTo> [-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
### SDSimple
```
Remove-NTFSAccess [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AccessType <AccessControlType>] [-AppliesTo <ApplyTo>] [-PassThru]
[<CommonParameters>]
[-AccessRights] <FileSystemRights2> [-AccessType <AccessControlType>] -AppliesTo <ApplyTo> [-RemoveSpecific]
[-PassThru] [<CommonParameters>]
```
### SDComplex
```
Remove-NTFSAccess [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AccessType <AccessControlType>] [-InheritanceFlags <InheritanceFlags>]
[-PropagationFlags <PropagationFlags>] [-PassThru] [<CommonParameters>]
[-PropagationFlags <PropagationFlags>] [-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
## DESCRIPTION
Removes the rights in `-AccessRights` from the access control entries (ACEs) of a file or a folder. An entry is addressed by the account in `-Account`, the access type in `-AccessType`, and the inheritance and propagation flags, which are given either as `-AppliesTo` or as `-InheritanceFlags` and `-PropagationFlags`.
Only the specified rights are taken away: when an entry grants more than `-AccessRights` names, the remaining rights stay in place, and the entry disappears only when all of its rights are removed. An `Allow` entry is always matched with the `Synchronize` right added to the specified rights. The flags must describe the entry as it exists on the item; when they do not, Windows splits the entry instead of removing the rights, so use the values that `Get-NTFSAccess` reports for the entry you want to change.
Only the specified rights are taken away: when an entry grants more than `-AccessRights` names, the remaining rights stay in place, and the entry disappears only when all of its rights are removed. An `Allow` entry is always matched with the `Synchronize` right added to the specified rights. The flags must describe the entry as it exists on the item; when they do not, Windows splits the entry instead of removing the rights, so use the values that `Get-NTFSAccess` reports for the entry you want to change. With `-RemoveSpecific`, the cmdlet removes only an entry that matches exactly.
Inherited entries cannot be removed from the item that inherits them. Remove them from the folder named in the `InheritedFrom` property, or run `Disable-NTFSAccessInheritance` on the item first, which copies the inherited entries into it as explicit ones that this cmdlet can then remove.
The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`, and `PathComplex` is the default. A command that works on a security descriptor, whether it is passed to `-SecurityDescriptor` or piped in, must therefore name `-AppliesTo` or `-InheritanceFlags` and `-PropagationFlags`; without one of them PowerShell cannot choose between the two `SD` sets and reports that the parameter set cannot be resolved. All relevant parameters bind by property name, so the output of `Get-NTFSAccess` and `Get-NTFSOrphanedAccess` can be piped directly into this cmdlet. The cmdlet writes no output unless `-PassThru` is used.
The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`, and `PathComplex` is the default. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets. All relevant parameters bind by property name, so the output of `Get-NTFSAccess` and `Get-NTFSOrphanedAccess` can be piped directly into this cmdlet. The cmdlet writes no output unless `-PassThru` is used.
## EXAMPLES
@ -146,7 +146,7 @@ Parameter Sets: PathSimple, SDSimple
Aliases:
Accepted values: ThisFolderOnly, ThisFolderSubfoldersAndFiles, ThisFolderAndSubfolders, ThisFolderAndFiles, SubfoldersAndFilesOnly, SubfoldersOnly, FilesOnly, ThisFolderSubfoldersAndFilesOneLevel, ThisFolderAndSubfoldersOneLevel, ThisFolderAndFilesOneLevel, SubfoldersAndFilesOnlyOneLevel, SubfoldersOnlyOneLevel, FilesOnlyOneLevel
Required: False
Required: True
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName)
@ -237,6 +237,22 @@ Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```
### -RemoveSpecific
Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
@ -288,6 +304,8 @@ If the ACL of an item cannot be written because access is denied, the cmdlet tri
Removing rights from an entry that does not exist is not an error; the cmdlet leaves the ACL unchanged.
Before 5.0.0, the `-RemoveSpecific` switch was missing, although version 4.1 had introduced it.
## RELATED LINKS
[Get-NTFSAccess](Get-NTFSAccess.md)

40
Docs/Cmdlets/Remove-NTFSAudit.md

@ -17,38 +17,38 @@ Removes an audit entry from a file or folder.
```
Remove-NTFSAudit [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AuditFlags <AuditFlags>] [-InheritanceFlags <InheritanceFlags>] [-PropagationFlags <PropagationFlags>]
[-PassThru] [<CommonParameters>]
[-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
### PathSimple
```
Remove-NTFSAudit [-Path] <String[]> [-Account] <IdentityReference2[]> [-AccessRights] <FileSystemRights2>
[-AuditFlags <AuditFlags>] [-AppliesTo <ApplyTo>] [-PassThru] [<CommonParameters>]
[-AuditFlags <AuditFlags>] -AppliesTo <ApplyTo> [-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
### SDSimple
```
Remove-NTFSAudit [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AuditFlags <AuditFlags>] [-AppliesTo <ApplyTo>] [-PassThru]
[<CommonParameters>]
[-AccessRights] <FileSystemRights2> [-AuditFlags <AuditFlags>] -AppliesTo <ApplyTo> [-RemoveSpecific]
[-PassThru] [<CommonParameters>]
```
### SDComplex
```
Remove-NTFSAudit [-SecurityDescriptor] <FileSystemSecurity2[]> [-Account] <IdentityReference2[]>
[-AccessRights] <FileSystemRights2> [-AuditFlags <AuditFlags>] [-InheritanceFlags <InheritanceFlags>]
[-PropagationFlags <PropagationFlags>] [-PassThru] [<CommonParameters>]
[-PropagationFlags <PropagationFlags>] [-RemoveSpecific] [-PassThru] [<CommonParameters>]
```
## DESCRIPTION
The `Remove-NTFSAudit` cmdlet removes an audit entry from the system access control list (SACL) of a file or folder. The cmdlet builds an audit entry from `-Account`, `-AccessRights`, `-AuditFlags`, and the inheritance and propagation flags, and removes that entry from the SACL. The audit entries of the account are matched by their inheritance and propagation flags, and the requested access rights and audit flags are then taken away from them: an entry that audits further rights keeps those rights and disappears only when nothing is left. To remove an entry completely, pass the same values that `Get-NTFSAudit` reports for it.
The `Remove-NTFSAudit` cmdlet removes an audit entry from the system access control list (SACL) of a file or folder. The cmdlet builds an audit entry from `-Account`, `-AccessRights`, `-AuditFlags`, and the inheritance and propagation flags, and removes that entry from the SACL. The audit entries of the account are matched by their inheritance and propagation flags, and the requested access rights and audit flags are then taken away from them: an entry that audits further rights keeps those rights and disappears only when nothing is left. To remove an entry completely, pass the same values that `Get-NTFSAudit` reports for it. With `-RemoveSpecific`, the cmdlet removes only an entry that matches exactly.
Because the inheritance and propagation flags take part in the match, they must describe the entry you want to remove. `-AppliesTo ThisFolderOnly` removes an entry that is not inherited by child items, which is also the shape of every audit entry on a file, while the default of the complex parameter sets removes an entry that applies to the folder, its subfolders, and its files. An entry that an item inherits from a parent folder is stored on that parent, so remove it there, or use `Clear-NTFSAudit` with `-DisableInheritance` to drop the inherited entries on the item.
In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path` and writes it back right away. In the `SDSimple` and `SDComplex` parameter sets it changes an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, and the change reaches the file system only when you pass the object to `Set-NTFSSecurityDescriptor`. `PathComplex` is the default parameter set; because it requires `-Path`, a command that uses `-SecurityDescriptor` must also specify `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` so that PowerShell can choose between `SDSimple` and `SDComplex`.
In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path` and writes it back right away. In the `SDSimple` and `SDComplex` parameter sets it changes an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, and the change reaches the file system only when you pass the object to `Set-NTFSSecurityDescriptor`. `PathComplex` is the default parameter set. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.
When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`, and `-AppliesTo` is `ThisFolderOnly`. All parameters bind by property name, and `-Path` also binds by value and through its `FullName` alias, so you can pipe the output of `Get-NTFSAudit`, `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` into the cmdlet. The cmdlet writes no object unless you use `-PassThru`.
When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`. All parameters bind by property name, and `-Path` also binds by value and through its `FullName` alias, so you can pipe the output of `Get-NTFSAudit`, `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` into the cmdlet. The cmdlet writes no object unless you use `-PassThru`.
## EXAMPLES
@ -123,7 +123,7 @@ Accept wildcard characters: False
### -AppliesTo
Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. The default is `ThisFolderOnly`.
Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.
```yaml
Type: ApplyTo
@ -131,9 +131,9 @@ Parameter Sets: PathSimple, SDSimple
Aliases:
Accepted values: ThisFolderOnly, ThisFolderSubfoldersAndFiles, ThisFolderAndSubfolders, ThisFolderAndFiles, SubfoldersAndFilesOnly, SubfoldersOnly, FilesOnly, ThisFolderSubfoldersAndFilesOneLevel, ThisFolderAndSubfoldersOneLevel, ThisFolderAndFilesOneLevel, SubfoldersAndFilesOnlyOneLevel, SubfoldersOnlyOneLevel, FilesOnlyOneLevel
Required: False
Required: True
Position: Named
Default value: ThisFolderOnly
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
@ -237,6 +237,22 @@ Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```
### -RemoveSpecific
Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.
```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
@ -290,6 +306,8 @@ If the security descriptor cannot be read or written because access is denied, t
The cmdlet reports no error when no entry matches the supplied values. Compare the result with `Get-NTFSAudit` to confirm that the entry is gone.
Before 5.0.0, the cmdlet had no `-RemoveSpecific` switch.
## RELATED LINKS
[Get-NTFSAudit](Get-NTFSAudit.md)

8
Docs/Concepts.md

@ -31,10 +31,10 @@ Most cmdlets accept either `-Path` or `-SecurityDescriptor`:
several changes and write them in one step.
When you pass a security descriptor to `Add-NTFSAccess`, `Remove-NTFSAccess`,
`Add-NTFSAudit`, or `Remove-NTFSAudit`, also specify `-AppliesTo` or the
`-InheritanceFlags` and `-PropagationFlags` parameters. Without them,
PowerShell cannot choose between the two security descriptor parameter sets
and reports that the parameter set cannot be resolved.
`Add-NTFSAudit`, or `Remove-NTFSAudit` without `-AppliesTo`, the cmdlet uses
the `-InheritanceFlags` and `-PropagationFlags` parameters and their defaults,
as it does for a path. Before 5.0.0, such a command failed, because PowerShell
couldn't choose between the two security descriptor parameter sets.
## Accounts

5
NTFSSecurity/AccessCmdlets/AddAccess.cs

@ -86,8 +86,9 @@ namespace NTFSSecurity
set { propagationFlags = value; }
}
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
// Mandatory, so that a command without it resolves to the Complex parameter set, also for -SecurityDescriptor.
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
public ApplyTo AppliesTo
{
get { return appliesTo; }

123
NTFSSecurity/AccessCmdlets/GetEffectiveAccess.cs

@ -69,12 +69,7 @@ namespace NTFSSecurity
{
base.BeginProcessing();
if (paths == null)
{
paths = new List<string>() { GetVariableValue("PWD").ToString() };
}
var securityPrivilege = privControl.GetPrivileges().Where(priv => priv.Privilege == ProcessPrivileges.Privilege.Security);
securityPrivilege = privControl.GetPrivileges().Where(priv => priv.Privilege == ProcessPrivileges.Privilege.Security).ToList();
if (securityPrivilege.Count() == 0)
{
this.WriteWarning("The user does not hold the Security Privliege and might not be able to read the effective permissions");
@ -90,10 +85,34 @@ namespace NTFSSecurity
protected override void ProcessRecord()
{
FileSystemInfo item = null;
if (ParameterSetName == "SecurityDescriptor")
{
foreach (var sd in securityDescriptors)
{
EffectiveAccessInfo result = null;
foreach (var path in paths)
try
{
result = EffectiveAccess.GetEffectiveAccess(sd, account, serverName);
}
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "ReadEffectivePermissionError", ErrorCategory.ReadError, sd));
continue;
}
WriteEffectiveAccess(result, sd.Item);
}
return;
}
// Like the other cmdlets, use the current location when -Path is omitted.
var targets = paths.Count > 0 ? paths : new List<string>() { GetVariableValue("PWD").ToString() };
foreach (var path in targets)
{
FileSystemInfo item = null;
EffectiveAccessInfo result = null;
try
@ -109,30 +128,7 @@ namespace NTFSSecurity
try
{
result = EffectiveAccess.GetEffectiveAccess(item, account, serverName);
if (!result.FromRemote)
{
WriteWarning("The effective rights can only be computed based on group membership on this" +
" computer. For more accurate results, calculate effective access rights on " +
"the target computer");
}
if (result.OperationFailed && securityPrivilege == null)
{
var ex = new Exception(string.Format("Could not get effective permissions from machine '{0}' maybe because the 'Security' privilege is not enabled which might be required. Enable the priviliges using 'Enable-Privileges'. The error was '{1}'", serverName, result.AuthzException.Message), result.AuthzException);
WriteError(new ErrorRecord(ex, "GetEffectiveAccessError", ErrorCategory.ReadError, item));
continue;
}
else if (result.OperationFailed)
{
var ex = new Exception(string.Format("Could not get effective permissions from machine '{0}'. The error is '{1}'", serverName, result.AuthzException.Message), result.AuthzException);
WriteError(new ErrorRecord(ex, "GetEffectiveAccessError", ErrorCategory.ReadError, item));
continue;
}
if (excludeNoneAccessEntries && result.Ace.AccessRights == FileSystemRights2.None)
continue;
}
//not sure if the following catch block willb be invoked, testing needed.
catch (UnauthorizedAccessException)
{
try
@ -142,53 +138,52 @@ namespace NTFSSecurity
FileSystemOwner.SetOwner(item, System.Security.Principal.WindowsIdentity.GetCurrent().User);
//--------------------
result = EffectiveAccess.GetEffectiveAccess(item, account, serverName);
if (!result.FromRemote)
{
WriteWarning("The effective rights can only be computed based on group membership on this" +
" computer. For more accurate results, calculate effective access rights on " +
"the target computer");
}
if (result.OperationFailed && securityPrivilege == null)
{
var ex = new Exception(string.Format("Could not get effective permissions from machine '{0}' maybe because the 'Security' privilege is not enabled which might be required. Enable the priviliges using 'Enable-Privileges'. The error was '{1}'", serverName, result.AuthzException.Message), result.AuthzException);
WriteError(new ErrorRecord(ex, "GetEffectiveAccessError", ErrorCategory.ReadError, item));
continue;
}
else if (result.OperationFailed)
{
var ex = new Exception(string.Format("Could not get effective permissions from machine '{0}'. The error is '{1}'", serverName, result.AuthzException.Message), result.AuthzException);
WriteError(new ErrorRecord(ex, "GetEffectiveAccessError", ErrorCategory.ReadError, item));
continue;
}
if (excludeNoneAccessEntries && result.Ace.AccessRights == FileSystemRights2.None)
continue;
//--------------------
FileSystemOwner.SetOwner(item, previousOwner);
}
catch (Exception ex2)
{
this.WriteError(new ErrorRecord(ex2, "ReadSecurityError", ErrorCategory.WriteError, path));
continue;
}
}
catch (Exception ex)
{
WriteError(new ErrorRecord(ex, "ReadEffectivePermissionError", ErrorCategory.ReadError, path));
continue;
}
finally
{
if (result != null)
{
WriteObject(result.Ace);
}
}
WriteEffectiveAccess(result, item);
}
}
private void WriteEffectiveAccess(EffectiveAccessInfo result, object target)
{
if (!result.FromRemote)
{
WriteWarning("The effective rights can only be computed based on group membership on this" +
" computer. For more accurate results, calculate effective access rights on " +
"the target computer");
}
if (result.OperationFailed)
{
var securityPrivilegeEnabled = securityPrivilege.Any(p => p.PrivilegeState == PrivilegeState.Enabled);
var message = securityPrivilegeEnabled ?
string.Format("Could not get effective permissions from machine '{0}'. The error is '{1}'", serverName, result.AuthzException.Message) :
string.Format("Could not get effective permissions from machine '{0}' maybe because the 'Security' privilege is not enabled which might be required. Enable the priviliges using 'Enable-Privileges'. The error was '{1}'", serverName, result.AuthzException.Message);
WriteError(new ErrorRecord(new Exception(message, result.AuthzException), "GetEffectiveAccessError", ErrorCategory.ReadError, target));
return;
}
// .NET adds Synchronize to every allow rule, so an account without access has Synchronize only.
if (excludeNoneAccessEntries && (result.Ace.AccessRights & ~FileSystemRights2.Synchronize) == FileSystemRights2.None)
{
return;
}
WriteObject(result.Ace);
}
}
}

44
NTFSSecurity/AccessCmdlets/GetOrphanedAccess.cs

@ -15,11 +15,21 @@ namespace NTFSSecurity
protected override void ProcessRecord()
{
IEnumerable<FileSystemAccessRule2> acl = null;
FileSystemInfo item = null;
if (ParameterSetName == "SD")
{
foreach (var sd in securityDescriptors)
{
WriteOrphanedAces(FileSystemAccessRule2.GetFileSystemAccessRules(sd, !ExcludeExplicit, !ExcludeInherited, getInheritedFrom), sd.FullName);
}
return;
}
foreach (var path in paths)
{
FileSystemInfo item = null;
IEnumerable<FileSystemAccessRule2> acl = null;
try
{
item = this.GetFileSystemInfo2(path);
@ -50,25 +60,33 @@ namespace NTFSSecurity
catch (Exception ex2)
{
this.WriteError(new ErrorRecord(ex2, "AddAceError", ErrorCategory.WriteError, path));
continue;
}
}
catch (Exception ex)
{
this.WriteWarning(string.Format("Could not read item {0}. The error was: {1}", path, ex.Message));
continue;
}
finally
{
if (acl != null)
{
var orphanedAces = acl.Where(ace => string.IsNullOrEmpty(ace.Account.AccountName));
orphanedSidCount += orphanedAces.Count();
WriteVerbose(string.Format("Item {0} knows about {1} orphaned SIDs in its ACL", path, orphanedAces.Count()));
WriteOrphanedAces(acl, path);
}
}
orphanedAces.ForEach(ace => WriteObject(ace));
}
}
private void WriteOrphanedAces(IEnumerable<FileSystemAccessRule2> acl, string path)
{
var orphanedAces = acl.Where(ace => string.IsNullOrEmpty(ace.Account.AccountName));
if (Account != null)
{
orphanedAces = orphanedAces.Where(ace => ace.Account == Account);
}
var orphanedAceList = orphanedAces.ToList();
orphanedSidCount += orphanedAceList.Count;
WriteVerbose(string.Format("Item {0} knows about {1} orphaned SIDs in its ACL", path, orphanedAceList.Count));
orphanedAceList.ForEach(ace => WriteObject(ace));
}
protected override void EndProcessing()
@ -77,4 +95,4 @@ namespace NTFSSecurity
base.EndProcessing();
}
}
}
}

23
NTFSSecurity/AccessCmdlets/RemoveAccess.cs

@ -16,7 +16,7 @@ namespace NTFSSecurity
private AccessControlType accessType = AccessControlType.Allow;
private InheritanceFlags inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
private PropagationFlags propagationFlags = PropagationFlags.None;
private ApplyTo appliesTo;
private ApplyTo appliesTo = ApplyTo.ThisFolderSubfoldersAndFiles;
private bool removeSpecific;
private bool passThru;
@ -87,14 +87,25 @@ namespace NTFSSecurity
set { propagationFlags = value; }
}
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
// Mandatory, so that a command without it resolves to the Complex parameter set, also for -SecurityDescriptor.
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
public ApplyTo AppliesTo
{
get { return appliesTo; }
set { appliesTo = value; }
}
/// <summary>
/// Removes only an entry that matches exactly, instead of taking the rights away from matching entries.
/// </summary>
[Parameter]
public SwitchParameter RemoveSpecific
{
get { return removeSpecific; }
set { removeSpecific = value; }
}
[Parameter]
public SwitchParameter PassThru
{
@ -136,7 +147,7 @@ namespace NTFSSecurity
try
{
FileSystemAccessRule2.RemoveFileSystemAccessRule(item, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags);
FileSystemAccessRule2.RemoveFileSystemAccessRule(item, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags, removeSpecific);
}
catch (UnauthorizedAccessException)
{
@ -147,7 +158,7 @@ namespace NTFSSecurity
FileSystemOwner.SetOwner(item, System.Security.Principal.WindowsIdentity.GetCurrent().User);
FileSystemAccessRule2.RemoveFileSystemAccessRule(item, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags);
FileSystemAccessRule2.RemoveFileSystemAccessRule(item, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags, removeSpecific);
FileSystemOwner.SetOwner(item, previousOwner);
}
@ -171,7 +182,7 @@ namespace NTFSSecurity
{
foreach (var sd in securityDescriptors)
{
FileSystemAccessRule2.RemoveFileSystemAccessRule(sd, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags);
FileSystemAccessRule2.RemoveFileSystemAccessRule(sd, account.ToList(), accessRights, accessType, inheritanceFlags, propagationFlags, removeSpecific);
if (passThru == true)
{

5
NTFSSecurity/AuditCmdlets/AddAudit.cs

@ -85,8 +85,9 @@ namespace NTFSSecurity
set { propagationFlags = value; }
}
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
// Mandatory, so that a command without it resolves to the Complex parameter set, also for -SecurityDescriptor.
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
public ApplyTo AppliesTo
{
get { return appliesTo; }

52
NTFSSecurity/AuditCmdlets/Get-OrphanedAudit.cs

@ -15,11 +15,28 @@ namespace NTFSSecurity.AuditCmdlets
protected override void ProcessRecord()
{
IEnumerable<FileSystemAuditRule2> acl;
FileSystemInfo item = null;
if (ParameterSetName == "SD")
{
foreach (var sd in securityDescriptors)
{
if (!sd.HasAuditSection)
{
var ex = new InvalidOperationException(string.Format(
"The security descriptor of '{0}' doesn't contain the audit entries, because it was read without the Security privilege.", sd.FullName));
WriteError(new ErrorRecord(ex, "ReadSecurityError", ErrorCategory.InvalidData, sd));
continue;
}
WriteOrphanedAces(FileSystemAuditRule2.GetFileSystemAuditRules(sd, !ExcludeExplicit, !ExcludeInherited, getInheritedFrom), sd.FullName);
}
return;
}
foreach (var p in paths)
{
FileSystemInfo item = null;
try
{
item = this.GetFileSystemInfo2(p);
@ -30,21 +47,38 @@ namespace NTFSSecurity.AuditCmdlets
continue;
}
IEnumerable<FileSystemAuditRule2> acl = null;
try
{
acl = FileSystemAuditRule2.GetFileSystemAuditRules(item, !ExcludeExplicit, !ExcludeInherited, getInheritedFrom);
var orphanedAces = acl.Where(ace => string.IsNullOrEmpty(ace.Account.AccountName));
orphanedSidCount += orphanedAces.Count();
this.WriteVerbose(string.Format("Item {0} knows about {1} orphaned SIDs in its ACL", p, orphanedAces.Count()));
this.WriteObject(orphanedAces);
}
catch (Exception ex)
{
this.WriteWarning(string.Format("Could not read item {0}. The error was: {1}", p, ex.Message));
continue;
}
// Outside the try block, so that a stopped pipeline isn't reported as a read error.
WriteOrphanedAces(acl, p);
}
}
private void WriteOrphanedAces(IEnumerable<FileSystemAuditRule2> acl, string path)
{
var orphanedAces = acl.Where(ace => string.IsNullOrEmpty(ace.Account.AccountName));
if (Account != null)
{
orphanedAces = orphanedAces.Where(ace => ace.Account == Account);
}
var orphanedAceList = orphanedAces.ToList();
orphanedSidCount += orphanedAceList.Count;
this.WriteVerbose(string.Format("Item {0} knows about {1} orphaned SIDs in its ACL", path, orphanedAceList.Count));
// One object per entry, not one collection per item
orphanedAceList.ForEach(ace => WriteObject(ace));
}
protected override void EndProcessing()
@ -53,4 +87,4 @@ namespace NTFSSecurity.AuditCmdlets
base.EndProcessing();
}
}
}
}

23
NTFSSecurity/AuditCmdlets/RemoveAudit.cs

@ -16,7 +16,7 @@ namespace NTFSSecurity
private AuditFlags auditFlags = AuditFlags.Failure | AuditFlags.Success;
private InheritanceFlags inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
private PropagationFlags propagationFlags = PropagationFlags.None;
private ApplyTo appliesTo;
private ApplyTo appliesTo = ApplyTo.ThisFolderSubfoldersAndFiles;
private bool removeSpecific;
private bool passThru;
@ -86,14 +86,25 @@ namespace NTFSSecurity
set { propagationFlags = value; }
}
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
// Mandatory, so that a command without it resolves to the Complex parameter set, also for -SecurityDescriptor.
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "PathSimple")]
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ParameterSetName = "SDSimple")]
public ApplyTo AppliesTo
{
get { return appliesTo; }
set { appliesTo = value; }
}
/// <summary>
/// Removes only an entry that matches exactly, instead of taking the rights away from matching entries.
/// </summary>
[Parameter]
public SwitchParameter RemoveSpecific
{
get { return removeSpecific; }
set { removeSpecific = value; }
}
[Parameter]
public SwitchParameter PassThru
{
@ -135,7 +146,7 @@ namespace NTFSSecurity
try
{
FileSystemAuditRule2.RemoveFileSystemAuditRule(item, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags);
FileSystemAuditRule2.RemoveFileSystemAuditRule(item, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags, removeSpecific);
}
catch (UnauthorizedAccessException)
{
@ -146,7 +157,7 @@ namespace NTFSSecurity
FileSystemOwner.SetOwner(item, System.Security.Principal.WindowsIdentity.GetCurrent().User);
FileSystemAuditRule2.RemoveFileSystemAuditRule(item, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags);
FileSystemAuditRule2.RemoveFileSystemAuditRule(item, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags, removeSpecific);
FileSystemOwner.SetOwner(item, previousOwner);
}
@ -170,7 +181,7 @@ namespace NTFSSecurity
{
foreach (var sd in securityDescriptors)
{
FileSystemAuditRule2.RemoveFileSystemAuditRule(sd, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags);
FileSystemAuditRule2.RemoveFileSystemAuditRule(sd, account.ToList(), accessRights, auditFlags, inheritanceFlags, propagationFlags, removeSpecific);
if (passThru == true)
{

50
NTFSSecurity/NTFSSecurity.format.ps1xml

@ -234,6 +234,56 @@
</TableControl>
</View>
<View>
<Name>Security2.SimpleFileSystemAccessRule</Name>
<ViewSelectedBy>
<TypeName>Security2.SimpleFileSystemAccessRule</TypeName>
</ViewSelectedBy>
<GroupBy>
<PropertyName>FullName</PropertyName>
<CustomControlName>SimpleFileSystemAccessRule2Grouping</CustomControlName>
</GroupBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>35</Width>
<Label>Account</Label>
</TableColumnHeader>
<TableColumnHeader>
<Label>Access Rights</Label>
</TableColumnHeader>
<TableColumnHeader>
<Label>Type</Label>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<ScriptBlock>
if ((Get-Module NTFSSecurity).PrivateData.ShowAccountSid)
{
'{0} ({1})' -f $_.Identity.AccountName, $_.Identity.Sid
}
else
{
$_.Identity.ToString()
}
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>AccessRights</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>AccessControlType</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>Security2.SimpleFileSystemAuditRule2</Name>
<ViewSelectedBy>

19
NTFSSecurity/SimpleAccessCmdlets/SimpleAccessCmdlets.cs

@ -32,6 +32,18 @@ namespace NTFSSecurity
protected override void ProcessRecord()
{
if (ParameterSetName == "SD")
{
foreach (var sd in securityDescriptors)
{
var sdAcl = FilterAccount(FileSystemAccessRule2.GetFileSystemAccessRules(sd, !ExcludeExplicit, !ExcludeInherited).Select(ace => ace.ToSimpleFileSystemAccessRule2())).ToList();
aceList.AddRange(sdAcl);
sdAcl.ForEach(ace => WriteObject(ace));
}
return;
}
//as this cmdlet retreives also the current working folder to show the permissions.
if (includeRootFolder & isFirstFolder)
{
@ -57,7 +69,7 @@ namespace NTFSSecurity
WriteVerbose(string.Format("New folder: {0}", item.FullName));
directoryList.Add(item);
var acl = FileSystemAccessRule2.GetFileSystemAccessRules(item, !ExcludeExplicit, !ExcludeInherited).Select(ace => ace.ToSimpleFileSystemAccessRule2());
var acl = FilterAccount(FileSystemAccessRule2.GetFileSystemAccessRules(item, !ExcludeExplicit, !ExcludeInherited).Select(ace => ace.ToSimpleFileSystemAccessRule2())).ToList();
try
{
@ -112,6 +124,11 @@ namespace NTFSSecurity
}
}
}
private IEnumerable<SimpleFileSystemAccessRule> FilterAccount(IEnumerable<SimpleFileSystemAccessRule> acl)
{
return Account == null ? acl : acl.Where(ace => ace.Identity == Account);
}
}
#endregion

260
NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml

@ -12,7 +12,7 @@
<maml:description>
<maml:para>Adds an access control entry (ACE) to the discretionary access control list (DACL) of a file or a folder. Every account in `-Account` receives the rights in `-AccessRights`, either as an `Allow` or as a `Deny` entry.</maml:para>
<maml:para>`-AccessRights` accepts the basic rights such as `Read`, `Modify`, and `FullControl` as well as the granular rights such as `CreateFiles` or `WriteAttributes`, and several values can be combined, for example `-AccessRights ReadData, WriteData, Delete`. For the mapping between the values of this module, the rights that Windows displays, and the entries of the advanced security dialog, see Concepts (../Concepts.md).</maml:para>
<maml:para>The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`; both describe the same ACE flags, and `PathComplex` is the default. A command that works on a security descriptor, whether it is passed to `-SecurityDescriptor` or piped in, must therefore name `-AppliesTo` or `-InheritanceFlags` and `-PropagationFlags`; without one of them PowerShell cannot choose between the two `SD` sets and reports that the parameter set cannot be resolved.</maml:para>
<maml:para>The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`; both describe the same ACE flags, and `PathComplex` is the default. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.</maml:para>
<maml:para>When `-AccessType`, `-AppliesTo`, `-InheritanceFlags`, and `-PropagationFlags` are omitted, the cmdlet adds an `Allow` ACE that applies to this folder, subfolders, and files, which corresponds to the inheritance flags `ContainerInherit, ObjectInherit` and no propagation flags. An `Allow` ACE always receives the `Synchronize` right in addition to the requested rights, inheritance and propagation flags are ignored on files, and rights for an account that already has an ACE with the same access type and the same flags are merged into that ACE. The cmdlet writes no output unless `-PassThru` is used, and a failure on one item is reported as a non-terminating error while the remaining items are processed.</maml:para>
<maml:para>`-Path` accepts pipeline input by value and by property name through its alias `FullName`, so output of `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` can be piped in. `-Account`, `-AccessRights`, `-AccessType`, `-InheritanceFlags`, and `-PropagationFlags` bind by property name as well, which lets you pipe `Security2.FileSystemAccessRule2` objects, or rows imported from a CSV file created from them, directly into the cmdlet.</maml:para>
</maml:description>
@ -101,10 +101,10 @@
</dev:type>
<dev:defaultValue>Allow</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The default is `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -126,7 +126,7 @@
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>PassThru</maml:name>
@ -225,10 +225,10 @@
</dev:type>
<dev:defaultValue>Allow</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The default is `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -250,7 +250,7 @@
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>PassThru</maml:name>
@ -565,17 +565,17 @@
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The default is `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
<maml:para>Specifies the scope of the ACE in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same ACE. The values ending in `OneLevel` limit inheritance to the direct children of the folder.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">ApplyTo</command:parameterValue>
<dev:type>
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>InheritanceFlags</maml:name>
@ -795,7 +795,7 @@
<maml:description>
<maml:para>The `Add-NTFSAudit` cmdlet adds an audit entry to the system access control list (SACL) of a file or folder. Windows then writes an event to the security log when the audited account uses one of the audited access rights on the item. `-AuditFlags Success` audits successful attempts, `-AuditFlags Failure` audits failed attempts, and the default audits both. For what the individual access rights permit, see Concepts (../Concepts.md).</maml:para>
<maml:para>In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path`, adds the entry, and writes the descriptor back right away. In the `SDSimple` and `SDComplex` parameter sets it adds the entry to an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned; that change only reaches the file system when you pass the object to `Set-NTFSSecurityDescriptor`. The simple sets describe the scope of the entry with the single `-AppliesTo` parameter, the complex sets with `-InheritanceFlags` and `-PropagationFlags`.</maml:para>
<maml:para>`PathComplex` is the default parameter set. Because that set requires `-Path`, a command that uses `-SecurityDescriptor` must also specify `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags`; otherwise PowerShell cannot decide between `SDSimple` and `SDComplex` and reports that the parameter set cannot be resolved.</maml:para>
<maml:para>`PathComplex` is the default parameter set. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.</maml:para>
<maml:para>When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`, and `-AppliesTo` is `ThisFolderSubfoldersAndFiles`, so both the simple and the complex set audit the item, its subfolders, and its files by default. Inheritance applies to folders only: when the item is a file, the cmdlet stores the entry without inheritance and propagation flags.</maml:para>
<maml:para>`-Path` accepts pipeline input by value and by property name through its `FullName` alias, so the output of `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` binds to it, and the remaining parameters bind by property name. The cmdlet writes no object unless you use `-PassThru`.</maml:para>
</maml:description>
@ -868,10 +868,10 @@
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. The default is `ThisFolderSubfoldersAndFiles`.</maml:para>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -893,7 +893,7 @@
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -992,10 +992,10 @@
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. The default is `ThisFolderSubfoldersAndFiles`.</maml:para>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -1017,7 +1017,7 @@
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -1336,17 +1336,17 @@
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. The default is `ThisFolderSubfoldersAndFiles`.</maml:para>
<maml:para>Specifies the scope of the audit entry with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. `ThisFolderOnly` audits the folder itself, `ThisFolderSubfoldersAndFiles` audits the folder and everything below it, `SubfoldersAndFilesOnly` audits the content but not the folder itself, and the values ending in `OneLevel` limit inheritance to the direct children. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">ApplyTo</command:parameterValue>
<dev:type>
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderSubfoldersAndFiles</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -4922,7 +4922,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:para>Calculates the rights an account really has on a file or a folder and writes the result as a single `Security2.FileSystemAccessRule2` object per item. The cmdlet evaluates the complete discretionary access control list (DACL) of the item against the group memberships of the account with the Windows Authorization API, so allow entries, deny entries, and inherited entries are combined the same way the Windows access check combines them. This is the equivalent of the "Effective Access" tab of the advanced security dialog.</maml:para>
<maml:para>The calculation covers the NTFS permissions of the item only. Share permissions are stored in a separate security descriptor and are not part of the result, so access over a network share can be more restrictive than this cmdlet reports.</maml:para>
<maml:para>When `-Account` is omitted, the account that runs the session is used. `-ServerName` selects the computer whose authorization manager resolves the group memberships of the account and defaults to `localhost`; when the remote authorization manager of the named computer cannot be reached, the cmdlet falls back to the local one and warns that the result is based on the group memberships known on this computer and may be inaccurate. Reading effective access relies on the Security privilege, and the cmdlet warns when the account does not hold it or the privilege is disabled.</maml:para>
<maml:para>Although `-Path` is optional, the cmdlet writes nothing when the parameter is omitted; pass a path or pipe items in. The `SecurityDescriptor` parameter set is accepted by the parameter binder but produces no output, so use `-Path` to query effective access.</maml:para>
<maml:para>When `-Path` is omitted, the cmdlet calculates the effective access to the current location. In the `SecurityDescriptor` parameter set, it calculates the effective access from a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, without reading the item again.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -4930,7 +4930,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="FullName">
<maml:name>Path</maml:name>
<maml:description>
<maml:para>Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. The cmdlet writes nothing when no path is supplied.</maml:para>
<maml:para>Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. When you omit the parameter, the cmdlet uses the current location.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
<dev:type>
@ -4954,7 +4954,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>ExcludeNoneAccessEntries</maml:name>
<maml:description>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. In this release the switch does not suppress anything: the cmdlet writes a result for every item it processes, even when the calculated access mask is `None`.</maml:para>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. Because every calculated result includes the `Synchronize` right, an item counts as without rights when `Synchronize` is the only right.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
@ -4980,7 +4980,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is accepted by the parameter binder but has no effect. The cmdlet produces no output in this parameter set; use `-Path` instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet calculates the effective access from the in-memory object instead of reading the item again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -5005,7 +5005,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>ExcludeNoneAccessEntries</maml:name>
<maml:description>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. In this release the switch does not suppress anything: the cmdlet writes a result for every item it processes, even when the calculated access mask is `None`.</maml:para>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. Because every calculated result includes the `Synchronize` right, an item counts as without rights when `Synchronize` is the only right.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
@ -5043,7 +5043,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>ExcludeNoneAccessEntries</maml:name>
<maml:description>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. In this release the switch does not suppress anything: the cmdlet writes a result for every item it processes, even when the calculated access mask is `None`.</maml:para>
<maml:para>Indicates that items on which the account has no rights at all are left out of the result. Because every calculated result includes the `Synchronize` right, an item counts as without rights when `Synchronize` is the only right.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
<dev:type>
@ -5055,7 +5055,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="FullName">
<maml:name>Path</maml:name>
<maml:description>
<maml:para>Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. The cmdlet writes nothing when no path is supplied.</maml:para>
<maml:para>Specifies the path of one or more files or folders the effective access is calculated for. Relative paths are resolved against the current location. The parameter accepts pipeline input by value and by property name through its alias `FullName`. When you omit the parameter, the cmdlet uses the current location.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">String[]</command:parameterValue>
<dev:type>
@ -5067,7 +5067,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is accepted by the parameter binder but has no effect. The cmdlet produces no output in this parameter set; use `-Path` instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet calculates the effective access from the in-memory object instead of reading the item again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -5130,6 +5130,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:alert>
<maml:para>When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), this cmdlet tries to enable the Backup, Restore, Take Ownership, and Security privileges while it runs and disables the privileges it enabled when it finishes. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group. If a privilege cannot be enabled, the cmdlet continues without it and writes a debug message.</maml:para>
<maml:para>Reading effective access needs the Security privilege. In a session that does not hold it, the cmdlet warns before it starts and the calculation may fail with an error. Use `Enable-Privileges` in an elevated session to enable the privilege, and `Get-Privileges` to see which privileges the session holds.</maml:para>
<maml:para>Before 5.0.0, `-ExcludeNoneAccessEntries` had no effect, and the cmdlet returned nothing without `-Path` or for `-SecurityDescriptor`.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -5512,7 +5513,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:para>Reads the discretionary access control list (DACL) of a file or a folder like `Get-NTFSAccess` and returns only the access control entries whose account name is empty. The account name of an entry is empty when Windows cannot translate the SID stored in the entry into an account name, which is what remains after the account the entry was created for has been deleted.</maml:para>
<maml:para>An entry counts as orphaned only as long as the name resolution fails, and the cmdlet cannot tell a deleted account from an account that cannot be looked up right now. A domain controller that is unreachable, a broken trust, or a SID from a domain the computer does not know make intact entries look orphaned as well. Confirm that the accounts are really gone before you remove anything, and run the search from a computer that can resolve all domains involved.</maml:para>
<maml:para>Relative paths are resolved against the current location, and the current location is searched when `-Path` is omitted. By default both explicit and inherited entries are returned, which means that the same orphaned entry appears on every item that inherits it; `-ExcludeInherited` reports it only on the item where it is defined. With `-Verbose`, the cmdlet reports the number of orphaned entries per item and the total at the end.</maml:para>
<maml:para>The `-Account` and `-SecurityDescriptor` parameters are inherited from `Get-NTFSAccess` and have no effect on this cmdlet. Entries are never filtered by account, and a security descriptor passed to `-SecurityDescriptor` is ignored; the cmdlet reads the current location instead.</maml:para>
<maml:para>`-Account` limits the result to the entries of one account, which you specify by its SID. With `-SecurityDescriptor`, the cmdlet examines a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned instead of reading the item again.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -5532,7 +5533,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts that cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5569,7 +5570,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet searches the path in `-Path` or the current location instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -5582,7 +5583,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts that cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5619,7 +5620,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts that cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5667,7 +5668,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet searches the path in `-Path` or the current location instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -5692,7 +5693,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:name>Security2.FileSystemSecurity2[]</maml:name>
</dev:type>
<maml:description>
<maml:para>Security descriptors are accepted by the parameter binder but ignored by this cmdlet.</maml:para>
<maml:para>You can pipe the security descriptors that `Get-NTFSSecurityDescriptor` returns to this cmdlet.</maml:para>
</maml:description>
</command:inputType>
<command:inputType>
@ -5700,7 +5701,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:name>Security2.IdentityReference2</maml:name>
</dev:type>
<maml:description>
<maml:para>An account is accepted by the parameter binder but ignored by this cmdlet.</maml:para>
<maml:para>An account name or a SID string binds to `-Account`.</maml:para>
</maml:description>
</command:inputType>
</command:inputTypes>
@ -5718,6 +5719,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:alert>
<maml:para>When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), this cmdlet tries to enable the Backup, Restore, Take Ownership, and Security privileges while it runs and disables the privileges it enabled when it finishes. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group. If a privilege cannot be enabled, the cmdlet continues without it and writes a debug message.</maml:para>
<maml:para>If the ACL of an item cannot be read because access is denied, the cmdlet tries once more after making the current account the owner of the item, and restores the previous owner afterwards. Changing the owner of an item requires the Take Ownership and Restore privileges, so this fallback only succeeds in an elevated session of an account that holds them.</maml:para>
<maml:para>Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor`, and after a path whose ACL could not be read, it returned the orphaned entries of the previous item again.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -5783,7 +5785,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:para>The `Get-NTFSOrphanedAudit` cmdlet returns the audit entries of a file or folder whose account cannot be translated into a name. An entry is called orphaned when its security identifier (SID) is still stored in the system access control list (SACL) but Windows cannot map that SID to a user or group, which usually happens after the account was deleted. Orphaned entries are shown with their SID instead of a name, and they keep auditing a security principal that no longer exists.</maml:para>
<maml:para>An entry is reported as orphaned whenever the name resolution fails at that moment, not only when the account is really gone. A domain account whose domain controller cannot be reached, an account from a domain whose trust relationship is broken, and an account from a forest the computer currently cannot contact all look exactly like a deleted account. Verify that an account no longer exists before you remove its entries with `Remove-NTFSAudit`.</maml:para>
<maml:para>The cmdlet is built on `Get-NTFSAudit` and reads the SACL of every item in `-Path`, using the current location when you omit the parameter. `-Path` accepts pipeline input by value and by property name through its `FullName` alias, so the output of `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` binds to it. `-ExcludeExplicit` and `-ExcludeInherited` narrow the entries that are examined, and `-Verbose` reports how many orphaned entries each item has and their total.</maml:para>
<maml:para>`Get-NTFSOrphanedAudit` inherits the `-Account` and `-SecurityDescriptor` parameters from `Get-NTFSAudit`, but it does not evaluate them. The entries are always read from the items in `-Path`, so a command that passes `-SecurityDescriptor` examines the current location instead of the descriptor.</maml:para>
<maml:para>`-Account` limits the result to the entries of one account, which you specify by its SID. With `-SecurityDescriptor`, the cmdlet examines a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned; a descriptor that was read without the Security privilege doesn't contain the audit entries, and the cmdlet writes an error for it.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -5803,7 +5805,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>Specifies an account in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not evaluate it, so the result always contains the entries of every account whose SID cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned audit entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5840,7 +5842,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>Specifies one or more security descriptors in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not read from it; the cmdlet always examines the items in `-Path` and therefore the current location when `-Path` is omitted. Use `Get-NTFSAudit -SecurityDescriptor` to inspect the audit entries of a security descriptor.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
<dev:type>
@ -5852,7 +5854,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>Specifies an account in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not evaluate it, so the result always contains the entries of every account whose SID cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned audit entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5889,7 +5891,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>Specifies an account in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not evaluate it, so the result always contains the entries of every account whose SID cannot be resolved.</maml:para>
<maml:para>Specifies the account whose orphaned audit entries are returned. Because the account cannot be resolved, specify it by its SID. When you omit the parameter, the cmdlet returns the entries of all accounts that cannot be resolved.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -5937,7 +5939,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>Specifies one or more security descriptors in the base cmdlet `Get-NTFSAudit`. `Get-NTFSOrphanedAudit` inherits the parameter but does not read from it; the cmdlet always examines the items in `-Path` and therefore the current location when `-Path` is omitted. Use `Get-NTFSAudit -SecurityDescriptor` to inspect the audit entries of a security descriptor.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet examines the in-memory objects instead of reading the items again.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
<dev:type>
@ -5969,7 +5971,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:name>Security2.IdentityReference2</maml:name>
</dev:type>
<maml:description>
<maml:para>An account name or a SID string binds to the inherited `-Account` parameter, which this cmdlet does not evaluate.</maml:para>
<maml:para>An account name or a SID string binds to `-Account`.</maml:para>
</maml:description>
</command:inputType>
</command:inputTypes>
@ -5979,7 +5981,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:name>Security2.FileSystemAuditRule2</maml:name>
</dev:type>
<maml:description>
<maml:para>The cmdlet returns the audit entries whose account SID cannot be translated into a name, each with the item, the unresolved account, the audited access rights, the audit flags, and the inheritance information. The entries of an item are written as a single collection rather than one object per entry, so store the result in a variable before you filter or format it; an item without orphaned entries still produces one empty collection, and a command placed directly after this cmdlet in the pipeline receives the collection instead of the individual entries.</maml:para>
<maml:para>The cmdlet returns the audit entries whose account SID cannot be translated into a name, each with the item, the unresolved account, the audited access rights, the audit flags, and the inheritance information. The cmdlet writes one object per entry.</maml:para>
</maml:description>
</command:returnValue>
</command:returnValues>
@ -5988,6 +5990,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<maml:para>When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), this cmdlet tries to enable the Backup, Restore, Take Ownership, and Security privileges while it runs and disables the privileges it enabled when it finishes. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group. If a privilege cannot be enabled, the cmdlet continues without it and writes a debug message.</maml:para>
<maml:para>Reading the SACL requires the Security privilege (`SeSecurityPrivilege`, "Manage auditing and security log"), so run this cmdlet in an elevated session of an account that holds that privilege. Without it the cmdlet reads the security descriptor without its SACL and reports no orphaned entries at all, which looks the same as a tree that has none.</maml:para>
<maml:para>If an item cannot be read, the cmdlet writes a warning and continues with the next item. Unlike `Get-NTFSAudit`, it does not try to take ownership of the item when access is denied.</maml:para>
<maml:para>Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor` and wrote the entries of each item as one collection.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -6010,7 +6013,7 @@ PS C:\&gt; Get-NTFSAudit -SecurityDescriptor $sd</dev:code>
<dev:code>PS C:\&gt; $orphaned = Get-NTFSOrphanedAudit -Path C:\Data -Verbose
PS C:\&gt; $orphaned | Select-Object FullName, Account, AccessRights, AuditFlags</dev:code>
<dev:remarks>
<maml:para>This command stores the result in a variable and then lists the item, the unresolved SID, the audited rights, and the audit flags of every orphaned entry. Storing the result first is necessary because the cmdlet writes one collection per item rather than one object per entry.</maml:para>
<maml:para>This command stores the result in a variable and then lists the item, the unresolved SID, the audited rights, and the audit flags of every orphaned entry.</maml:para>
</dev:remarks>
</command:example>
<command:example>
@ -6359,7 +6362,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:para>Reads the access control entries of folders and writes them as `Security2.SimpleFileSystemAccessRule` objects whose rights are reduced to the three values `Read`, `Write`, and `Delete`. Reading rights such as `ReadAttributes` or `Traverse` become `Read`, changing rights such as `CreateFiles`, `WriteAttributes`, `ChangePermissions`, or `TakeOwnership` become `Write`, and `Delete` and `DeleteSubdirectoriesAndFiles` become `Delete`; `FullControl` becomes all three. The result answers who may read, change, or delete in a folder without the detail of the full ACL.</maml:para>
<maml:para>The second simplification is that repetitions are left out. The first folder the cmdlet processes is reported with all of its entries, and for every folder that follows only the entries are reported that its parent folder does not already cover. An entry is covered when the parent has an entry for the same account and access type that includes at least the same simple rights. This makes a recursive listing show where permissions actually change instead of repeating the inherited ones on every level, and it requires the parent folder to be processed before its children, which `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` do by default.</maml:para>
<maml:para>`-IncludeRootFolder` is on by default and adds the parent folder of the first path as the baseline for the comparison, which is why the first result usually belongs to the folder above the one that was asked for. Use `-IncludeRootFolder:$false` to start the comparison at the first path itself.</maml:para>
<maml:para>The cmdlet only processes folders; a path that points to a file is skipped silently. Relative paths are resolved against the current location, and the current location is used when `-Path` is omitted. `-ExcludeInherited` and `-ExcludeExplicit` work as in `Get-NTFSAccess`, while `-Account` and `-SecurityDescriptor` are inherited from that cmdlet and have no effect here.</maml:para>
<maml:para>The cmdlet only processes folders; a path that points to a file is skipped silently, while the security descriptor of a file is reported. Relative paths are resolved against the current location, and the current location is used when `-Path` is omitted. `-ExcludeInherited`, `-ExcludeExplicit`, and `-Account` work as in `Get-NTFSAccess`. With `-SecurityDescriptor`, the cmdlet reports the entries of a `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, without comparing them with a parent folder.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -6379,7 +6382,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts.</maml:para>
<maml:para>Specifies the account whose entries are returned. When you omit the parameter, the cmdlet returns the entries of all accounts.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -6427,7 +6430,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet reads the path in `-Path` or the current location instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet reports the entries of the in-memory objects instead of reading the items again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -6440,7 +6443,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts.</maml:para>
<maml:para>Specifies the account whose entries are returned. When you omit the parameter, the cmdlet returns the entries of all accounts.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -6488,7 +6491,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="IdentityReference, ID">
<maml:name>Account</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. The cmdlet always returns the entries of all accounts.</maml:para>
<maml:para>Specifies the account whose entries are returned. When you omit the parameter, the cmdlet returns the entries of all accounts.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">IdentityReference2</command:parameterValue>
<dev:type>
@ -6548,7 +6551,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName, ByValue)" position="1" aliases="none">
<maml:name>SecurityDescriptor</maml:name>
<maml:description>
<maml:para>This parameter is inherited from `Get-NTFSAccess` and has no effect. A security descriptor passed here is ignored, and the cmdlet reads the path in `-Path` or the current location instead.</maml:para>
<maml:para>Specifies one or more security descriptors that `Get-NTFSSecurityDescriptor` returned. The cmdlet reports the entries of the in-memory objects instead of reading the items again.</maml:para>
<maml:para>A security descriptor contains information about the owner of the object, and the primary group of an object. The security descriptor also contains two access control lists (ACL). The first list is called the discretionary access control lists (DACL), and describes who should have access to an object and what type of access to grant. The second list is called the system access control lists (SACL) and defines what type of auditing to record for an object.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">FileSystemSecurity2[]</command:parameterValue>
@ -6573,7 +6576,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:name>Security2.FileSystemSecurity2[]</maml:name>
</dev:type>
<maml:description>
<maml:para>Security descriptors are accepted by the parameter binder but ignored by this cmdlet.</maml:para>
<maml:para>You can pipe the security descriptors that `Get-NTFSSecurityDescriptor` returns to this cmdlet.</maml:para>
</maml:description>
</command:inputType>
<command:inputType>
@ -6581,7 +6584,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:name>Security2.IdentityReference2</maml:name>
</dev:type>
<maml:description>
<maml:para>An account is accepted by the parameter binder but ignored by this cmdlet.</maml:para>
<maml:para>An account name or a SID string binds to `-Account`.</maml:para>
</maml:description>
</command:inputType>
</command:inputTypes>
@ -6591,7 +6594,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:name>Security2.SimpleFileSystemAccessRule</maml:name>
</dev:type>
<maml:description>
<maml:para>One object per reported entry, with the folder in `FullName` and `Name`, the account in `Identity`, the access type in `AccessControlType`, and the simplified rights `Read`, `Write`, and `Delete` in `AccessRights`.</maml:para>
<maml:para>One object per reported entry, with the folder in `FullName` and `Name`, the account in `Identity`, the access type in `AccessControlType`, and the simplified rights `Read`, `Write`, and `Delete` in `AccessRights`. The default view is a table with the `Account`, `Access Rights`, and `Type` columns, grouped by folder.</maml:para>
</maml:description>
</command:returnValue>
</command:returnValues>
@ -6599,6 +6602,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:alert>
<maml:para>When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), this cmdlet tries to enable the Backup, Restore, Take Ownership, and Security privileges while it runs and disables the privileges it enabled when it finishes. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group. If a privilege cannot be enabled, the cmdlet continues without it and writes a debug message.</maml:para>
<maml:para>The simplified rights hide which exact rights an account holds. Use `Get-NTFSAccess` when you need the full access control entry, and `Get-NTFSEffectiveAccess` when you need the rights that result from all entries together.</maml:para>
<maml:para>Before 5.0.0, the cmdlet ignored `-Account` and `-SecurityDescriptor`, and its output had no table view.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -7618,9 +7622,9 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</command:details>
<maml:description>
<maml:para>Removes the rights in `-AccessRights` from the access control entries (ACEs) of a file or a folder. An entry is addressed by the account in `-Account`, the access type in `-AccessType`, and the inheritance and propagation flags, which are given either as `-AppliesTo` or as `-InheritanceFlags` and `-PropagationFlags`.</maml:para>
<maml:para>Only the specified rights are taken away: when an entry grants more than `-AccessRights` names, the remaining rights stay in place, and the entry disappears only when all of its rights are removed. An `Allow` entry is always matched with the `Synchronize` right added to the specified rights. The flags must describe the entry as it exists on the item; when they do not, Windows splits the entry instead of removing the rights, so use the values that `Get-NTFSAccess` reports for the entry you want to change.</maml:para>
<maml:para>Only the specified rights are taken away: when an entry grants more than `-AccessRights` names, the remaining rights stay in place, and the entry disappears only when all of its rights are removed. An `Allow` entry is always matched with the `Synchronize` right added to the specified rights. The flags must describe the entry as it exists on the item; when they do not, Windows splits the entry instead of removing the rights, so use the values that `Get-NTFSAccess` reports for the entry you want to change. With `-RemoveSpecific`, the cmdlet removes only an entry that matches exactly.</maml:para>
<maml:para>Inherited entries cannot be removed from the item that inherits them. Remove them from the folder named in the `InheritedFrom` property, or run `Disable-NTFSAccessInheritance` on the item first, which copies the inherited entries into it as explicit ones that this cmdlet can then remove.</maml:para>
<maml:para>The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`, and `PathComplex` is the default. A command that works on a security descriptor, whether it is passed to `-SecurityDescriptor` or piped in, must therefore name `-AppliesTo` or `-InheritanceFlags` and `-PropagationFlags`; without one of them PowerShell cannot choose between the two `SD` sets and reports that the parameter set cannot be resolved. All relevant parameters bind by property name, so the output of `Get-NTFSAccess` and `Get-NTFSOrphanedAccess` can be piped directly into this cmdlet. The cmdlet writes no output unless `-PassThru` is used.</maml:para>
<maml:para>The cmdlet has four parameter sets. The `Path` sets read the item from disk and write the changed DACL back immediately, while the `SD` sets change a `Security2.FileSystemSecurity2` object returned by `Get-NTFSSecurityDescriptor` in memory until `Set-NTFSSecurityDescriptor` writes it back. The `Simple` sets take `-AppliesTo`, the `Complex` sets take `-InheritanceFlags` and `-PropagationFlags`, and `PathComplex` is the default. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets. All relevant parameters bind by property name, so the output of `Get-NTFSAccess` and `Get-NTFSOrphanedAccess` can be piped directly into this cmdlet. The cmdlet writes no output unless `-PassThru` is used.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -7707,7 +7711,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>Allow</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the entry that is addressed, in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same entry. Use the scope that `Get-NTFSAccess` shows in the "Applies to" column of the entry.</maml:para>
@ -7745,6 +7749,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAccess</maml:name>
@ -7831,7 +7846,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>Allow</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the entry that is addressed, in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same entry. Use the scope that `Get-NTFSAccess` shows in the "Applies to" column of the entry.</maml:para>
@ -7869,6 +7884,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAccess</maml:name>
@ -7999,6 +8025,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAccess</maml:name>
@ -8130,6 +8167,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
</command:syntax>
<command:parameters>
@ -8169,7 +8217,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the entry that is addressed, in the wording of the Windows security dialog, for example `ThisFolderOnly`, `ThisFolderAndSubfolders`, or `SubfoldersAndFilesOnly`. The cmdlet translates the value into the equivalent inheritance and propagation flags, so this parameter and the pair `-InheritanceFlags` and `-PropagationFlags` are two ways to describe the same entry. Use the scope that `Get-NTFSAccess` shows in the "Applies to" column of the entry.</maml:para>
@ -8242,6 +8290,18 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an entry that matches the account, the access rights, the access type, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights away from the matching entries.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:parameters>
<command:inputTypes>
<command:inputType>
@ -8324,6 +8384,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:para>When the module setting `EnablePrivileges` is `$true` (the default in the `PrivateData` section of NTFSSecurity.psd1), this cmdlet tries to enable the Backup, Restore, Take Ownership, and Security privileges while it runs and disables the privileges it enabled when it finishes. These privileges are only available in an elevated session of an account that holds them, such as a member of the local Administrators group. If a privilege cannot be enabled, the cmdlet continues without it and writes a debug message.</maml:para>
<maml:para>If the ACL of an item cannot be written because access is denied, the cmdlet tries once more after making the current account the owner of the item, and restores the previous owner afterwards. Changing the owner of an item requires the Take Ownership and Restore privileges, so this fallback only succeeds in an elevated session of an account that holds them.</maml:para>
<maml:para>Removing rights from an entry that does not exist is not an error; the cmdlet leaves the ACL unchanged.</maml:para>
<maml:para>Before 5.0.0, the `-RemoveSpecific` switch was missing, although version 4.1 had introduced it.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>
@ -8397,10 +8458,10 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</maml:description>
</command:details>
<maml:description>
<maml:para>The `Remove-NTFSAudit` cmdlet removes an audit entry from the system access control list (SACL) of a file or folder. The cmdlet builds an audit entry from `-Account`, `-AccessRights`, `-AuditFlags`, and the inheritance and propagation flags, and removes that entry from the SACL. The audit entries of the account are matched by their inheritance and propagation flags, and the requested access rights and audit flags are then taken away from them: an entry that audits further rights keeps those rights and disappears only when nothing is left. To remove an entry completely, pass the same values that `Get-NTFSAudit` reports for it.</maml:para>
<maml:para>The `Remove-NTFSAudit` cmdlet removes an audit entry from the system access control list (SACL) of a file or folder. The cmdlet builds an audit entry from `-Account`, `-AccessRights`, `-AuditFlags`, and the inheritance and propagation flags, and removes that entry from the SACL. The audit entries of the account are matched by their inheritance and propagation flags, and the requested access rights and audit flags are then taken away from them: an entry that audits further rights keeps those rights and disappears only when nothing is left. To remove an entry completely, pass the same values that `Get-NTFSAudit` reports for it. With `-RemoveSpecific`, the cmdlet removes only an entry that matches exactly.</maml:para>
<maml:para>Because the inheritance and propagation flags take part in the match, they must describe the entry you want to remove. `-AppliesTo ThisFolderOnly` removes an entry that is not inherited by child items, which is also the shape of every audit entry on a file, while the default of the complex parameter sets removes an entry that applies to the folder, its subfolders, and its files. An entry that an item inherits from a parent folder is stored on that parent, so remove it there, or use `Clear-NTFSAudit` with `-DisableInheritance` to drop the inherited entries on the item.</maml:para>
<maml:para>In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path` and writes it back right away. In the `SDSimple` and `SDComplex` parameter sets it changes an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, and the change reaches the file system only when you pass the object to `Set-NTFSSecurityDescriptor`. `PathComplex` is the default parameter set; because it requires `-Path`, a command that uses `-SecurityDescriptor` must also specify `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` so that PowerShell can choose between `SDSimple` and `SDComplex`.</maml:para>
<maml:para>When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`, and `-AppliesTo` is `ThisFolderOnly`. All parameters bind by property name, and `-Path` also binds by value and through its `FullName` alias, so you can pipe the output of `Get-NTFSAudit`, `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` into the cmdlet. The cmdlet writes no object unless you use `-PassThru`.</maml:para>
<maml:para>In the `PathSimple` and `PathComplex` parameter sets the cmdlet reads the security descriptor of every item in `-Path` and writes it back right away. In the `SDSimple` and `SDComplex` parameter sets it changes an in-memory `Security2.FileSystemSecurity2` object that `Get-NTFSSecurityDescriptor` returned, and the change reaches the file system only when you pass the object to `Set-NTFSSecurityDescriptor`. `PathComplex` is the default parameter set. A command without `-AppliesTo` uses a `Complex` set, also when it works on a security descriptor. Before 5.0.0, a command that used `-SecurityDescriptor` without `-AppliesTo`, `-InheritanceFlags`, or `-PropagationFlags` failed, because PowerShell couldn't choose between the two `SD` sets.</maml:para>
<maml:para>When you omit them, `-AuditFlags` is `Success, Failure`, `-InheritanceFlags` is `ContainerInherit, ObjectInherit`, `-PropagationFlags` is `None`. All parameters bind by property name, and `-Path` also binds by value and through its `FullName` alias, so you can pipe the output of `Get-NTFSAudit`, `Get-ChildItem`, `Get-ChildItem2`, and `Get-Item2` into the cmdlet. The cmdlet writes no object unless you use `-PassThru`.</maml:para>
</maml:description>
<command:syntax>
<command:syntaxItem>
@ -8471,10 +8532,10 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. The default is `ThisFolderOnly`.</maml:para>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -8496,7 +8557,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderOnly</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -8526,6 +8587,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAudit</maml:name>
@ -8595,10 +8667,10 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. The default is `ThisFolderOnly`.</maml:para>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValueGroup>
<command:parameterValue required="false" command:variableLength="false">ThisFolderOnly</command:parameterValue>
@ -8620,7 +8692,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderOnly</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -8650,6 +8722,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAudit</maml:name>
@ -8781,6 +8864,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
<command:syntaxItem>
<maml:name>Remove-NTFSAudit</maml:name>
@ -8912,6 +9006,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.</maml:para>
</maml:description>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:syntaxItem>
</command:syntax>
<command:parameters>
@ -8939,17 +9044,17 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<command:parameter required="true" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AppliesTo</maml:name>
<maml:description>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. The default is `ThisFolderOnly`.</maml:para>
<maml:para>Specifies the scope of the audit entry to remove with a single value instead of the `-InheritanceFlags` and `-PropagationFlags` pair, in the same wording the Advanced Security Settings dialog uses. The value must describe the entry as `Get-NTFSAudit` reports it, otherwise nothing is removed. Without `-AppliesTo`, the cmdlet uses `-InheritanceFlags` and `-PropagationFlags`, whose defaults describe `ThisFolderSubfoldersAndFiles`.</maml:para>
</maml:description>
<command:parameterValue required="true" variableLength="false">ApplyTo</command:parameterValue>
<dev:type>
<maml:name>ApplyTo</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>ThisFolderOnly</dev:defaultValue>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="True (ByPropertyName)" position="named" aliases="none">
<maml:name>AuditFlags</maml:name>
@ -9023,6 +9128,18 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
</dev:type>
<dev:defaultValue>None</dev:defaultValue>
</command:parameter>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="named" aliases="none">
<maml:name>RemoveSpecific</maml:name>
<maml:description>
<maml:para>Indicates that the cmdlet removes only an audit entry that matches the account, the access rights, the audit flags, and the inheritance and propagation flags exactly, and leaves all other entries unchanged. Without this switch, the cmdlet takes the specified rights and audit flags away from the matching entries.</maml:para>
</maml:description>
<command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
<dev:type>
<maml:name>SwitchParameter</maml:name>
<maml:uri />
</dev:type>
<dev:defaultValue>False</dev:defaultValue>
</command:parameter>
</command:parameters>
<command:inputTypes>
<command:inputType>
@ -9106,6 +9223,7 @@ PS C:\Data&gt; Get-NTFSSecurityDescriptor</dev:code>
<maml:para>Reading and writing the SACL requires the Security privilege (`SeSecurityPrivilege`, "Manage auditing and security log"), so run this cmdlet in an elevated session of an account that holds that privilege. Without it, the cmdlet writes a non-terminating `RemoveAceError` whose message states that a required privilege is not held by the client, and the item is left unchanged.</maml:para>
<maml:para>If the security descriptor cannot be read or written because access is denied, the cmdlet takes ownership of the item, repeats the operation, and restores the previous owner. If the second attempt fails as well, the cmdlet writes an error, and the ownership change is not rolled back.</maml:para>
<maml:para>The cmdlet reports no error when no entry matches the supplied values. Compare the result with `Get-NTFSAudit` to confirm that the entry is gone.</maml:para>
<maml:para>Before 5.0.0, the cmdlet had no `-RemoveSpecific` switch.</maml:para>
</maml:alert>
</maml:alertSet>
<command:examples>

11
Security2/EffectiveAccess.cs

@ -8,20 +8,23 @@ namespace Security2
public class EffectiveAccess
{
public static EffectiveAccessInfo GetEffectiveAccess(FileSystemInfo item, IdentityReference2 id, string serverName)
{
return GetEffectiveAccess(new FileSystemSecurity2(item), id, serverName);
}
public static EffectiveAccessInfo GetEffectiveAccess(FileSystemSecurity2 sd, IdentityReference2 id, string serverName)
{
bool remoteServerAvailable = false;
Exception authzAccessCheckException = null;
var win32 = new Win32();
var fss = new FileSystemSecurity2(item);
var effectiveAccessMask = win32.GetEffectiveAccess(fss.SecurityDescriptor, id, serverName, out remoteServerAvailable, out authzAccessCheckException);
var effectiveAccessMask = win32.GetEffectiveAccess(sd.SecurityDescriptor, id, serverName, out remoteServerAvailable, out authzAccessCheckException);
var ace = new FileSystemAccessRule((SecurityIdentifier)id, (FileSystemRights)effectiveAccessMask, AccessControlType.Allow);
return new EffectiveAccessInfo(
new FileSystemAccessRule2(ace, item),
new FileSystemAccessRule2(ace, sd.Item),
remoteServerAvailable,
authzAccessCheckException);
}

2
Security2/FileSystem/FileSystemAccessRule2 Class/FileSystemAccessRule2.RemoveFileSystemAccessRules.cs

@ -137,7 +137,7 @@ namespace Security2
foreach (var account in accounts)
{
aces.Add(RemoveFileSystemAccessRule(sd, account, rights, type, inheritanceFlags, propagationFlags));
aces.Add(RemoveFileSystemAccessRule(sd, account, rights, type, inheritanceFlags, propagationFlags, removeSpecific));
}
return aces;

22
Security2/FileSystem/FileSystemAuditRule2 Class/FileSystemAuditRule2.RemoveFileSystemAuditRule.cs

@ -6,7 +6,7 @@ namespace Security2
{
public partial class FileSystemAuditRule2
{
public static void RemoveFileSystemAuditRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights2 rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
public static void RemoveFileSystemAuditRule(FileSystemInfo item, IdentityReference2 account, FileSystemRights2 rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, bool removeSpecific = false)
{
FileSystemAuditRule ace = null;
@ -17,7 +17,10 @@ namespace Security2
ace = (FileSystemAuditRule)sd.AuditRuleFactory(account, (int)rights, false, inheritanceFlags, propagationFlags, type);
sd.RemoveAuditRule(ace);
if (removeSpecific)
sd.RemoveAuditRuleSpecific(ace);
else
sd.RemoveAuditRule(ace);
file.SetAccessControl(sd);
}
@ -28,7 +31,10 @@ namespace Security2
var sd = directory.GetAccessControl(AccessControlSections.Audit);
ace = (FileSystemAuditRule)sd.AuditRuleFactory(account, (int)rights, false, inheritanceFlags, propagationFlags, type);
sd.RemoveAuditRule(ace);
if (removeSpecific)
sd.RemoveAuditRuleSpecific(ace);
else
sd.RemoveAuditRule(ace);
directory.SetAccessControl(sd);
}
@ -38,7 +44,7 @@ namespace Security2
{
foreach (var account in accounts)
{
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags, removeSpecific);
}
}
@ -65,17 +71,17 @@ namespace Security2
}
}
public static void RemoveFileSystemAuditRule(string path, IdentityReference2 account, FileSystemRights2 rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
public static void RemoveFileSystemAuditRule(string path, IdentityReference2 account, FileSystemRights2 rights, AuditFlags type, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, bool removeSpecific = false)
{
if (File.Exists(path))
{
var item = new FileInfo(path);
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags, removeSpecific);
}
else
{
var item = new DirectoryInfo(path);
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags);
RemoveFileSystemAuditRule(item, account, rights, type, inheritanceFlags, propagationFlags, removeSpecific);
}
}
@ -106,7 +112,7 @@ namespace Security2
foreach (var account in accounts)
{
aces.Add(RemoveFileSystemAuditRule(sd, account, rights, type, inheritanceFlags, propagationFlags));
aces.Add(RemoveFileSystemAuditRule(sd, account, rights, type, inheritanceFlags, propagationFlags, removeSpecific));
}
return aces;

183
Tests/Access.Tests.ps1

@ -35,3 +35,186 @@ Describe 'Get-NTFSAccess' {
}
}
}
Describe 'Get-NTFSEffectiveAccess' {
BeforeAll {
$effectiveFile = New-TestSandboxItem -Sandbox $sandbox -Name 'Effective'
Assert-TestSandboxPath -Sandbox $sandbox -Path $effectiveFile
$acl = Get-Acl -LiteralPath $effectiveFile
$guests = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList 'S-1-5-32-546'
$acl.AddAccessRule((New-Object -TypeName 'System.Security.AccessControl.FileSystemAccessRule' -ArgumentList (
$guests, [System.Security.AccessControl.FileSystemRights]::FullControl,
[System.Security.AccessControl.AccessControlType]::Deny
)))
Set-Acl -LiteralPath $effectiveFile -AclObject $acl
}
It 'Should leave out an account without access when -ExcludeNoneAccessEntries is used' {
$result = @(Get-NTFSEffectiveAccess -Path $effectiveFile -Account 'S-1-5-32-546' -ExcludeNoneAccessEntries -WarningAction SilentlyContinue -ErrorAction Stop)
$result | Should -BeNullOrEmpty
}
It 'Should return an account with access when -ExcludeNoneAccessEntries is used' {
$result = @(Get-NTFSEffectiveAccess -Path $effectiveFile -ExcludeNoneAccessEntries -WarningAction SilentlyContinue -ErrorAction Stop)
$result | Should -HaveCount 1
}
It 'Should use the current location when -Path is omitted' {
$result = @(Get-NTFSEffectiveAccess -WarningAction SilentlyContinue -ErrorAction Stop)
$result | Should -HaveCount 1
$result[0].FullName | Should -BeLike ('*\{0}' -f (Split-Path -Path $sandbox -Leaf))
}
It 'Should compute the effective access of a security descriptor' {
$sd = Get-NTFSSecurityDescriptor -Path $effectiveFile
$result = @(Get-NTFSEffectiveAccess -SecurityDescriptor $sd -WarningAction SilentlyContinue -ErrorAction Stop)
$result | Should -HaveCount 1
$result[0].FullName | Should -Be $effectiveFile
}
}
Describe 'Get-NTFSOrphanedAccess' {
BeforeAll {
$orphanedFile = New-TestSandboxItem -Sandbox $sandbox -Name 'Orphaned'
Assert-TestSandboxPath -Sandbox $sandbox -Path $orphanedFile
$acl = Get-Acl -LiteralPath $orphanedFile
foreach ($sid in 'S-1-5-21-1-2-3-1001', 'S-1-5-21-1-2-3-1002') {
$acl.AddAccessRule((New-Object -TypeName 'System.Security.AccessControl.FileSystemAccessRule' -ArgumentList (
(New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $sid),
[System.Security.AccessControl.FileSystemRights]::ReadData, [System.Security.AccessControl.AccessControlType]::Allow
)))
}
Set-Acl -LiteralPath $orphanedFile -AclObject $acl
}
It 'Should return the entries whose account cannot be resolved' {
@(Get-NTFSOrphanedAccess -Path $orphanedFile) | Should -HaveCount 2
}
It 'Should return only the entries of -Account' {
$result = @(Get-NTFSOrphanedAccess -Path $orphanedFile -Account 'S-1-5-21-1-2-3-1002')
$result | Should -HaveCount 1
$result[0].Account.Sid | Should -Be 'S-1-5-21-1-2-3-1002'
}
It 'Should read the entries of a security descriptor' {
$sd = Get-NTFSSecurityDescriptor -Path $orphanedFile
$result = @(Get-NTFSOrphanedAccess -SecurityDescriptor $sd)
$result | Should -HaveCount 2
$result | ForEach-Object -Process { $_.FullName | Should -Be $orphanedFile }
}
}
Describe 'Get-NTFSSimpleAccess' {
BeforeAll {
$simpleFolder = New-TestSandboxItem -Sandbox $sandbox -Name 'Simple' -Directory
Assert-TestSandboxPath -Sandbox $sandbox -Path $simpleFolder
$acl = Get-Acl -LiteralPath $simpleFolder
$acl.AddAccessRule((New-Object -TypeName 'System.Security.AccessControl.FileSystemAccessRule' -ArgumentList (
(New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList 'S-1-1-0'),
[System.Security.AccessControl.FileSystemRights]::ReadData, [System.Security.AccessControl.AccessControlType]::Allow
)))
Set-Acl -LiteralPath $simpleFolder -AclObject $acl
}
It 'Should return only the entries of -Account' {
$result = @(Get-NTFSSimpleAccess -Path $simpleFolder -Account 'S-1-1-0' -IncludeRootFolder:$false)
$result | Should -Not -BeNullOrEmpty
$result | ForEach-Object -Process { $_.Identity.Sid | Should -Be 'S-1-1-0' }
}
It 'Should read the entries of a security descriptor' {
$sd = Get-NTFSSecurityDescriptor -Path $simpleFolder
$result = @(Get-NTFSSimpleAccess -SecurityDescriptor $sd)
$result | Should -Not -BeNullOrEmpty
$result | ForEach-Object -Process { $_.FullName | Should -Be $simpleFolder }
}
It 'Should show the entries as a table with the account, the rights, and the type' {
$text = Get-NTFSSimpleAccess -Path $simpleFolder -IncludeRootFolder:$false | Out-String -Width 200
$text | Should -Match 'Account\s+Access Rights\s+Type'
}
}
Describe 'Remove-NTFSAccess' {
Context 'With -RemoveSpecific' {
BeforeEach {
$removeFolder = New-TestSandboxItem -Sandbox $sandbox -Name 'RemoveSpecific' -Directory
$sd = Get-NTFSSecurityDescriptor -Path $removeFolder
Add-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights Modify
function Get-EveryoneRule {
$sd.SecurityDescriptor.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) |
Where-Object -FilterScript { $_.IdentityReference.Value -eq 'S-1-1-0' }
}
}
It 'Should keep an entry that does not match exactly' {
Remove-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData -RemoveSpecific
(Get-EveryoneRule).FileSystemRights.HasFlag([System.Security.AccessControl.FileSystemRights]::Modify) | Should -BeTrue
}
It 'Should remove an entry that matches exactly' {
Remove-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights Modify -RemoveSpecific
Get-EveryoneRule | Should -BeNullOrEmpty
}
It 'Should take the rights away from a matching entry without -RemoveSpecific' {
Remove-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData
$rule = Get-EveryoneRule
$rule | Should -Not -BeNullOrEmpty
$rule.FileSystemRights.HasFlag([System.Security.AccessControl.FileSystemRights]::ReadData) | Should -BeFalse
}
}
}
Describe 'Security descriptor parameter sets' {
BeforeAll {
$folder = New-TestSandboxItem -Sandbox $sandbox -Name 'ParameterSets' -Directory
}
# Before 5.0.0, PowerShell could not choose between the SDSimple and SDComplex parameter sets.
It '<_> should accept -SecurityDescriptor without -AppliesTo or the flag parameters' -ForEach @(
'Add-NTFSAccess', 'Remove-NTFSAccess', 'Add-NTFSAudit', 'Remove-NTFSAudit'
) {
$sd = Get-NTFSSecurityDescriptor -Path $folder
{ & $_ -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData -ErrorAction Stop } | Should -Not -Throw
}
It 'Add-NTFSAccess should apply the entry to the folder, its subfolders, and files by default' {
$sd = Get-NTFSSecurityDescriptor -Path $folder
Add-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData
$rule = $sd.SecurityDescriptor.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) |
Where-Object -FilterScript { $_.IdentityReference.Value -eq 'S-1-1-0' }
$rule.InheritanceFlags | Should -Be ([System.Security.AccessControl.InheritanceFlags] 'ContainerInherit, ObjectInherit')
$rule.PropagationFlags | Should -Be ([System.Security.AccessControl.PropagationFlags]::None)
}
It 'Add-NTFSAccess should still take -AppliesTo for a security descriptor' {
$sd = Get-NTFSSecurityDescriptor -Path $folder
Add-NTFSAccess -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData -AppliesTo ThisFolderOnly
$rule = $sd.SecurityDescriptor.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) |
Where-Object -FilterScript { $_.IdentityReference.Value -eq 'S-1-1-0' }
$rule.InheritanceFlags | Should -Be ([System.Security.AccessControl.InheritanceFlags]::None)
}
}

49
Tests/Audit.Tests.ps1

@ -123,7 +123,56 @@ Describe 'Add-NTFSAudit' {
}
}
Describe 'Get-NTFSOrphanedAudit' {
BeforeAll {
$orphanedFile = New-TestSandboxItem -Sandbox $sandbox -Name 'OrphanedAudit'
}
# Before 5.0.0, the cmdlet wrote the entries of an item as one collection and ignored -Account.
It 'Should return one object per entry whose account cannot be resolved' -Skip:(-not $canReadAudit) {
foreach ($sid in 'S-1-5-21-1-2-3-1001', 'S-1-5-21-1-2-3-1002') {
Add-NTFSAudit -Path $orphanedFile -Account $sid -AccessRights ReadData -InheritanceFlags None -PropagationFlags None
}
$result = @(Get-NTFSOrphanedAudit -Path $orphanedFile)
$result | Should -HaveCount 2
$result | ForEach-Object -Process { $_ | Should -BeOfType [Security2.FileSystemAuditRule2] }
}
It 'Should return only the entries of -Account' -Skip:(-not $canReadAudit) {
$result = @(Get-NTFSOrphanedAudit -Path $orphanedFile -Account 'S-1-5-21-1-2-3-1002')
$result | Should -HaveCount 1
}
}
Describe 'Remove-NTFSAudit' {
Context 'With -RemoveSpecific' {
BeforeEach {
$removeFolder = New-TestSandboxItem -Sandbox $sandbox -Name 'RemoveSpecific' -Directory
$sd = Get-NTFSSecurityDescriptor -Path $removeFolder
Add-NTFSAudit -SecurityDescriptor $sd -Account 'Everyone' -AccessRights Modify
function Get-EveryoneAuditRule {
$sd.SecurityDescriptor.GetAuditRules($true, $false, [System.Security.Principal.SecurityIdentifier]) |
Where-Object -FilterScript { $_.IdentityReference.Value -eq 'S-1-1-0' }
}
}
It 'Should keep an audit entry that does not match exactly' {
Remove-NTFSAudit -SecurityDescriptor $sd -Account 'Everyone' -AccessRights ReadData -RemoveSpecific
(Get-EveryoneAuditRule).FileSystemRights.HasFlag([System.Security.AccessControl.FileSystemRights]::Modify) | Should -BeTrue
}
It 'Should remove an audit entry that matches exactly' {
Remove-NTFSAudit -SecurityDescriptor $sd -Account 'Everyone' -AccessRights Modify -RemoveSpecific
Get-EveryoneAuditRule | Should -BeNullOrEmpty
}
}
Context 'With -PassThru' {
It 'Should return the audit entries of the item, not its access entries' -Skip:(-not $canReadAudit) {
$file = New-TestSandboxItem -Sandbox $sandbox -Name 'PassThru'

Loading…
Cancel
Save