diff --git a/build.ps1 b/build.ps1 index 305177296..e964962be 100644 --- a/build.ps1 +++ b/build.ps1 @@ -5,11 +5,6 @@ mkdir $BIN/Modules -ErrorAction SilentlyContinue # Deploy PowerShell modules cd $BIN/Modules robocopy ../../test/Pester Pester /s /e -robocopy ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility Microsoft.PowerShell.Utility /s /e -cp ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/CoreClr/* Microsoft.PowerShell.Utility -robocopy ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Security Microsoft.PowerShell.Security /s /e -robocopy ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Management Microsoft.PowerShell.Management /s /e -robocopy ../../src/monad/monad/miscfiles/modules/PSDiagnostics PSDiagnostics /s /e cd ../.. # Publish PowerShell diff --git a/build.sh b/build.sh index 28b390dbd..717c695af 100755 --- a/build.sh +++ b/build.sh @@ -8,14 +8,6 @@ mkdir -p $BIN/Modules ( cd $BIN/Modules cp -r ../../test/Pester . - cp -r ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility . - cp ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/CoreClr/* Microsoft.PowerShell.Utility - cp -r ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Security . - cp -r ../../src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Management . - cp -r ../../src/monad/monad/miscfiles/modules/PSDiagnostics . - OMI=Microsoft.PowerShell.Commands.Omi - mkdir -p $OMI - ln -sf $BIN/$OMI.dll $OMI/ ) # Build native components diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 new file mode 100644 index 000000000..425e64b78 --- /dev/null +++ b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1 @@ -0,0 +1,99 @@ +@{ +GUID="EEFCB906-B326-4E99-9F54-8B4BB6EF3C6D" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.1.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +NestedModules="Microsoft.PowerShell.Commands.Management.dll" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390785' +AliasesToExport = @("gcb", "scb") +FunctionsToExport = @() +CmdletsToExport=@("Add-Content", + "Clear-Content", + "Clear-ItemProperty", + "Join-Path", + "Convert-Path", + "Copy-ItemProperty", + "Get-EventLog", + "Clear-EventLog", + "Write-EventLog", + "Limit-EventLog", + "Show-EventLog", + "New-EventLog", + "Remove-EventLog", + "Get-ChildItem", + "Get-Content", + "Get-ItemProperty", + "Get-ItemPropertyValue", + "Get-WmiObject", + "Invoke-WmiMethod", + "Move-ItemProperty", + "Get-Location", + "Set-Location", + "Push-Location", + "Pop-Location", + "New-PSDrive", + "Remove-PSDrive", + "Get-PSDrive", + "Get-Item", + "New-Item", + "Set-Item", + "Remove-Item", + "Move-Item", + "Rename-Item", + "Copy-Item", + "Clear-Item", + "Invoke-Item", + "Get-PSProvider", + "New-ItemProperty", + "Split-Path", + "Test-Path", + "Get-Process", + "Stop-Process", + "Wait-Process", + "Debug-Process", + "Start-Process", + "Remove-ItemProperty", + "Remove-WmiObject", + "Rename-ItemProperty", + "Register-WmiEvent", + "Resolve-Path", + "Get-Service", + "Stop-Service", + "Start-Service", + "Suspend-Service", + "Resume-Service", + "Restart-Service", + "Set-Service", + "New-Service", + "Set-Content", + "Set-ItemProperty", + "Set-WmiInstance", + "Get-Transaction", + "Start-Transaction", + "Complete-Transaction", + "Undo-Transaction", + "Use-Transaction", + "New-WebServiceProxy", + "Get-HotFix", + "Test-Connection", + "Enable-ComputerRestore", + "Disable-ComputerRestore", + "Checkpoint-Computer", + "Get-ComputerRestorePoint", + "Restart-Computer", + "Stop-Computer", + "Restore-Computer", + "Add-Computer", + "Remove-Computer", + "Test-ComputerSecureChannel", + "Reset-ComputerMachinePassword", + "Rename-Computer", + "Get-ControlPanelItem", + "Show-ControlPanelItem", + "Clear-Recyclebin", + "Get-Clipboard", + "Set-Clipboard") +} diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 new file mode 100644 index 000000000..a0198eea5 --- /dev/null +++ b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1 @@ -0,0 +1,14 @@ +@{ +GUID="A94C8C7E-9810-47C0-B8AF-65089C13A35A" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.0.0.0" +PowerShellVersion="3.0" +CLRVersion="4.0" +AliasesToExport = @() +FunctionsToExport = @() +CmdletsToExport="Get-Acl", "Set-Acl", "Get-PfxCertificate", "Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "Get-AuthenticodeSignature", "Set-AuthenticodeSignature", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-CmsMessage", "Unprotect-CmsMessage", "Protect-CmsMessage" +NestedModules="Microsoft.PowerShell.Security.dll" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390786' +} diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 new file mode 100644 index 000000000..8183aa29c --- /dev/null +++ b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -0,0 +1,27 @@ +@{ +GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59" +Author="Microsoft Corporation" +CompanyName="Microsoft Corporation" +Copyright="© Microsoft Corporation. All rights reserved." +ModuleVersion="3.1.0.0" +PowerShellVersion="3.0" +CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide", + "Out-File", "Out-String", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json", + "Register-ObjectEvent", "Register-EngineEvent", "Wait-Event", "Get-Event", "Remove-Event", + "Get-EventSubscriber", "Unregister-Event", "New-Event", "Add-Member", "Add-Type", "Compare-Object", + "ConvertFrom-StringData", "Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias", + "Invoke-Expression", "Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random", + "Get-UICulture", "Get-FileHash", "Get-Unique", "Import-Alias", "Import-LocalizedData", + "Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date", + "Start-Sleep", "Tee-Object", "Measure-Command", "Update-TypeData", "Update-FormatData", + "Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object", + "Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable", + "Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug", + "Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", + "Get-PSBreakpoint", "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack", + "Unblock-File", "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", + "Get-RunspaceDebug", "Wait-Debugger", "Convert-String", "New-TemporaryFile", "New-Guid", "Format-Hex", + "Import-PowerShellDataFile", "ConvertFrom-SddlString" +NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1" +HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390787' +} diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 new file mode 100644 index 000000000..79f16b047 --- /dev/null +++ b/src/Microsoft.PowerShell.Linux.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 @@ -0,0 +1,580 @@ +function Get-FileHash +{ + [CmdletBinding(DefaultParameterSetName = "Path", HelpURI = "http://go.microsoft.com/fwlink/?LinkId=517145")] + param( + [Parameter(Mandatory, ParameterSetName="Path", Position = 0)] + [System.String[]] + $Path, + + [Parameter(Mandatory, ParameterSetName="LiteralPath", ValueFromPipelineByPropertyName = $true)] + [Alias("PSPath")] + [System.String[]] + $LiteralPath, + + [Parameter(Mandatory, ParameterSetName="Stream")] + [System.IO.Stream] + $InputStream, + + [ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")] + [System.String] + $Algorithm="SHA256" + ) + + begin + { + # Construct the strongly-typed crypto object + + # First see if it has a FIPS algorithm + $hasherType = "System.Security.Cryptography.${Algorithm}CryptoServiceProvider" -as [Type] + if ($hasherType) + { + $hasher = $hasherType::New() + } + else + { + # Check if the type is supported in the current system + $algorithmType = "System.Security.Cryptography.${Algorithm}" -as [Type] + if ($algorithmType) + { + if ($Algorithm -eq "MACTripleDES") + { + $hasher = $algorithmType::New() + } + else + { + $hasher = $algorithmType::Create() + } + } + else + { + $errorId = "AlgorithmTypeNotSupported" + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::AlgorithmTypeNotSupported -f $Algorithm + $exception = [System.InvalidOperationException]::New($errorMessage) + $errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null) + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + } + + function GetStreamHash + { + param( + [System.IO.Stream] + $InputStream, + + [System.String] + $RelatedPath, + + [System.Security.Cryptography.HashAlgorithm] + $Hasher) + + # Compute file-hash using the crypto object + [Byte[]] $computedHash = $Hasher.ComputeHash($InputStream) + [string] $hash = [BitConverter]::ToString($computedHash) -replace '-','' + + if ($RelatedPath -eq $null) + { + $retVal = [PSCustomObject] @{ + Algorithm = $Algorithm.ToUpperInvariant() + Hash = $hash + } + } + else + { + $retVal = [PSCustomObject] @{ + Algorithm = $Algorithm.ToUpperInvariant() + Hash = $hash + Path = $RelatedPath + } + } + $retVal.psobject.TypeNames.Insert(0, "Microsoft.Powershell.Utility.FileHash") + $retVal + } + } + + process + { + if($PSCmdlet.ParameterSetName -eq "Stream") + { + GetStreamHash -InputStream $InputStream -RelatedPath $null -Hasher $hasher + } + else + { + $pathsToProcess = @() + if($PSCmdlet.ParameterSetName -eq "LiteralPath") + { + $pathsToProcess += Resolve-Path -LiteralPath $LiteralPath | Foreach-Object ProviderPath + } + if($PSCmdlet.ParameterSetName -eq "Path") + { + $pathsToProcess += Resolve-Path $Path | Foreach-Object ProviderPath + } + + foreach($filePath in $pathsToProcess) + { + if(Test-Path -LiteralPath $filePath -PathType Container) + { + continue + } + + try + { + # Read the file specified in $FilePath as a Byte array + [system.io.stream]$stream = [system.io.file]::OpenRead($filePath) + GetStreamHash -InputStream $stream -RelatedPath $filePath -Hasher $hasher + } + catch [Exception] + { + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_ + Write-Error -Message $errorMessage -Category ReadError -ErrorId "FileReadError" -TargetObject $FilePath + return + } + finally + { + if($stream) + { + $stream.Dispose() + } + } + } + } + } +} + +<# This cmdlet is used to create a new temporary file in $env:temp #> +function New-TemporaryFile +{ + [CmdletBinding( + HelpURI='http://go.microsoft.com/fwlink/?LinkId=526726', + SupportsShouldProcess=$true)] + [OutputType([System.IO.FileInfo])] + Param() + + Begin + { + try + { + if($PSCmdlet.ShouldProcess($env:TEMP)) + { + $tempFilePath = [System.IO.Path]::GetTempFileName() + } + } + catch + { + $errorRecord = [System.Management.Automation.ErrorRecord]::new($_.Exception,"NewTemporaryFileWriteError", "WriteError", $env:TEMP) + Write-Error -ErrorRecord $errorRecord + return + } + + if($tempFilePath) + { + Get-Item $tempFilePath + } + } +} + +<# This cmdlet is used to generate a new guid #> +function New-Guid +{ + [CmdletBinding(HelpURI='http://go.microsoft.com/fwlink/?LinkId=526920')] + [OutputType([System.Guid])] + Param() + + Begin + { + [Guid]::NewGuid() + } +} + +<############################################################################################ +# Format-Hex cmdlet helps in displaying the Hexadecimal equivalent of the input data. +############################################################################################> +function Format-Hex +{ + [CmdletBinding( + DefaultParameterSetName="Path", + HelpUri="http://go.microsoft.com/fwlink/?LinkId=526919")] + [Alias("fhx")] + [OutputType("Microsoft.PowerShell.Commands.ByteCollection")] + param + ( + [Parameter (Mandatory=$true, Position=0, ParameterSetName="Path")] + [ValidateNotNullOrEmpty()] + [string[]] $Path, + + [Parameter (Mandatory=$true, ParameterSetName="LiteralPath")] + [ValidateNotNullOrEmpty()] + [Alias("PSPath")] + [string[]] $LiteralPath, + + [Parameter(Mandatory=$true, ParameterSetName="ByInputObject", ValueFromPipeline=$true)] + [Object] $InputObject, + + [Parameter (ParameterSetName="ByInputObject")] + [ValidateSet("Ascii", "UTF32", "UTF7", "UTF8", "BigEndianUnicode", "Unicode")] + [string] $Encoding = "Ascii" + ) + + begin + { + <############################################################################################ + # The ConvertToHexadecimalHelper is a helper method used to fetch unicode bytes from the + # input data and display the hexadecimial representaion of the of the input data in bytes. + ############################################################################################> + function ConvertToHexadecimalHelper + { + param + ( + [Byte[]] $inputBytes, + [string] $path, + [Uint32] $offset + ) + + # This section is used to display the hexadecimal + # representaion of the of the input data in bytes. + if($inputBytes -ne $null) + { + $byteCollectionObject = [Microsoft.PowerShell.Commands.ByteCollection]::new($offset, $inputBytes, $path) + Write-Output -InputObject $byteCollectionObject + } + } + + <############################################################################################ + # The ProcessFileContent is a helper method used to fetch file contents in blocks and + # process it to support displaying hexadecimal formating of the fetched content. + ############################################################################################> + function ProcessFileContent + { + param + ( + [string] $filePath, + [boolean] $isLiteralPath + ) + + if($isLiteralPath) + { + $resolvedPaths = Resolve-Path -LiteralPath $filePath + } + else + { + $resolvedPaths = Resolve-Path -Path $filePath + } + + # If Path resolution has failed then a corresponding non-terminating error is + # written to the pipeline. We continue processing any remaining files. + if($resolvedPaths -eq $null) + { + return + } + + if($resolvedPaths.Count -gt 1) + { + # write a non-terminating error message indicating that path specified is resolving to multiple file system paths. + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexResolvePathError -f $filePath + Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::InvalidData) -ErrorId "FormatHexResolvePathError" + } + + $targetFilePath = $resolvedPaths.ProviderPath + + + if($targetFilePath -ne $null) + { + $bufferSize = 16 + $buffer = [byte[]]::new($bufferSize) + + try + { + try + { + $currentFileStream = [System.IO.File]::Open($targetFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) + } + catch + { + # Failed to access the file. Write a non terminating error to the pipeline + # and move on with the remaining files. + $exception = $_.Exception + if($null -ne $_.Exception -and + $null -ne $_.Exception.InnerException) + { + $exception = $_.Exception.InnerException + } + + $errorRecord = [System.Management.Automation.ErrorRecord]::new($exception,"FormatHexFileAccessError", ([System.Management.Automation.ErrorCategory]::ReadError), $targetFilePath) + $PSCmdlet.WriteError($errorRecord) + } + + if($null -ne $currentFileStream) + { + $srcStream = [System.IO.BinaryReader]::new($currentFileStream) + $displayHeader = $true + $offset = 0 + $blockCounter = 0 + while($numberOfBytesRead = $srcStream.Read($buffer, 0, $bufferSize)) + { + ConvertToHexadecimalHelper $buffer $targetFilePath $offset + $displayHeader = $false + $blockCounter++; + + # Updating the offset value. + $offset = $blockCounter*0x10 + } + } + } + finally + { + If($null -ne $currentFileStream) + { + $currentFileStream.Dispose() + } + If($null -ne $srcStream) + { + $srcStream.Dispose() + } + } + } + } + } + + process + { + switch($PSCmdlet.ParameterSetName) + { + "Path" + { + ProcessFileContent $Path $false + } + "LiteralPath" + { + ProcessFileContent $LiteralPath $true + } + "ByInputObject" + { + # If it's an actual byte or a byte array, then we directly use it for hexadecimal formatting. + if(($InputObject -is [Byte[]]) -or $InputObject -is [Byte]) + { + ConvertToHexadecimalHelper $InputObject $null + } + # If the input data is of string type then directly get bytes out of it. + elseif($InputObject -is [string]) + { + # The ValidateSet arribute on the Encoding paramter makes sure that only + # valid values (supported on all paltforms where Format-Hex is avaliable) + # are allowed through user input. + $inputBytes = [Text.Encoding]::$Encoding.GetBytes($InputObject) + ConvertToHexadecimalHelper $inputBytes $null + } + elseif($InputObject -is [System.IO.FileSystemInfo]) + { + # If file path is provided as an input, use the file contents to show the hexadecimal format. + $filePath = ([System.IO.FileSystemInfo]$InputObject).FullName + ProcessFileContent $filePath $false + } + else + { + # Otherwise, write a non-terminating error message indicating that input object type is not supported. + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexTypeNotSupported -f $InputObject.GetType() + Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::ParserError) -ErrorId "FormatHexFailureTypeNotSupported" + } + } + } + } +} + +## Imports a PowerShell Data File - a PowerShell hashtable defined in +## a file (such as a Module manifest, session configuration file) +function Import-PowerShellDataFile +{ + [CmdletBinding(DefaultParameterSetName = "ByPath", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=623621")] + [OutputType("System.Collections.Hashtable")] + param( + [Parameter(ParameterSetName = "ByPath", Position = 0)] + [String[]] $Path, + + [Parameter(ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = $true)] + [Alias("PSPath")] + [String[]] $LiteralPath + ) + + begin + { + function ThrowInvalidDataFile + { + param($resolvedPath, $extraError) + + $errorId = "CouldNotParseAsPowerShellDataFile$extraError" + $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData + $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::CouldNotParseAsPowerShellDataFile -f $resolvedPath + $exception = [System.InvalidOperationException]::New($errorMessage) + $errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null) + $PSCmdlet.WriteError($errorRecord) + } + } + + process + { + foreach($resolvedPath in (Resolve-Path @PSBoundParameters)) + { + $parseErrors = $null + $ast = [System.Management.Automation.Language.Parser]::ParseFile(($resolvedPath.ProviderPath), [ref] $null, [ref] $parseErrors) + if ($parseErrors.Length -gt 0) + { + ThrowInvalidDataFile $resolvedPath + } + else + { + $data = $ast.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $false ) + if($data) + { + $data.SafeGetValue() + } + else + { + ThrowInvalidDataFile $resolvedPath "NoHashtableRoot" + } + } + } + } +} + +## Converts a SDDL string into an object-based representation of a security +## descriptor +function ConvertFrom-SddlString +{ + [CmdletBinding(HelpUri = "http://go.microsoft.com/fwlink/?LinkId=623636")] + param( + ## The string representing the security descriptor in SDDL syntax + [Parameter(Mandatory, Position = 0)] + [String] $Sddl, + + ## The type of rights that this SDDL string represents, if any. + [Parameter()] + [ValidateSet( + "FileSystemRights", "RegistryRights", "ActiveDirectoryRights", + "MutexRights", "SemaphoreRights", "CryptoKeyRights", + "EventWaitHandleRights")] + $Type + ) + + ## Translates a SID into a NT Account + function ConvertTo-NtAccount + { + param($Sid) + + if($Sid) + { + $securityIdentifier = [System.Security.Principal.SecurityIdentifier] $Sid + + try + { + $ntAccount = $securityIdentifier.Translate([System.Security.Principal.NTAccount]).ToString() + } + catch{} + + $ntAccount + } + } + + ## Gets the access rights that apply to an access mask, preferring right types + ## of 'Type' if specified. + function Get-AccessRights + { + param($AccessMask, $Type) + + ## All the types of access rights understood by .NET + $rightTypes = [Ordered] @{ + "FileSystemRights" = [System.Security.AccessControl.FileSystemRights] + "RegistryRights" = [System.Security.AccessControl.RegistryRights] + "ActiveDirectoryRights" = [System.DirectoryServices.ActiveDirectoryRights] + "MutexRights" = [System.Security.AccessControl.MutexRights] + "SemaphoreRights" = [System.Security.AccessControl.SemaphoreRights] + "CryptoKeyRights" = [System.Security.AccessControl.CryptoKeyRights] + "EventWaitHandleRights" = [System.Security.AccessControl.EventWaitHandleRights] + } + $typesToExamine = $rightTypes.Values + + ## If they know the access mask represents a certain type, prefer its names + ## (i.e.: CreateLink for the registry over CreateDirectories for the filesystem) + if($Type) + { + $typesToExamine = @($rightTypes[$Type]) + $typesToExamine + } + + + ## Stores the access types we've found that apply + $foundAccess = @() + + ## Store the access types we've already seen, so that we don't report access + ## flags that are essentially duplicate. Many of the access values in the different + ## enumerations have the same value but with different names. + $foundValues = @{} + + ## Go through the entries in the different right types, and see if they apply to the + ## provided access mask. If they do, then add that to the result. + foreach($rightType in $typesToExamine) + { + foreach($accessFlag in [Enum]::GetNames($rightType)) + { + $longKeyValue = [long] $rightType::$accessFlag + if(-not $foundValues.ContainsKey($longKeyValue)) + { + $foundValues[$longKeyValue] = $true + if(($AccessMask -band $longKeyValue) -eq ($longKeyValue)) + { + $foundAccess += $accessFlag + } + } + } + } + + $foundAccess | Sort-Object + } + + ## Converts an ACE into a string representation + function ConvertTo-AceString + { + param( + [Parameter(ValueFromPipeline)] + $Ace, + $Type + ) + + process + { + foreach($aceEntry in $Ace) + { + $AceString = (ConvertTo-NtAccount $aceEntry.SecurityIdentifier) + ": " + $aceEntry.AceQualifier + if($aceEntry.AceFlags -ne "None") + { + $AceString += " " + $aceEntry.AceFlags + } + + if($aceEntry.AccessMask) + { + $foundAccess = Get-AccessRights $aceEntry.AccessMask $Type + + if($foundAccess) + { + $AceString += " ({0})" -f ($foundAccess -join ", ") + } + } + + $AceString + } + } + } + + $rawSecurityDescriptor = [Security.AccessControl.CommonSecurityDescriptor]::new($false,$false,$Sddl) + + $owner = ConvertTo-NtAccount $rawSecurityDescriptor.Owner + $group = ConvertTo-NtAccount $rawSecurityDescriptor.Group + $discretionaryAcl = ConvertTo-AceString $rawSecurityDescriptor.DiscretionaryAcl $Type + $systemAcl = ConvertTo-AceString $rawSecurityDescriptor.SystemAcl $Type + + [PSCustomObject] @{ + Owner = $owner + Group = $group + DiscretionaryAcl = @($discretionaryAcl) + SystemAcl = @($systemAcl) + RawDescriptor = $rawSecurityDescriptor + } +} diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psd1 b/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psd1 new file mode 100644 index 000000000..3d73330c0 Binary files /dev/null and b/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psd1 differ diff --git a/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psm1 b/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psm1 new file mode 100644 index 000000000..d36168f27 Binary files /dev/null and b/src/Microsoft.PowerShell.Linux.Host/Modules/PSDiagnostics/PSDiagnostics.psm1 differ diff --git a/src/Microsoft.PowerShell.Linux.Host/project.json b/src/Microsoft.PowerShell.Linux.Host/project.json index d1d98a1e3..1230eb868 100644 --- a/src/Microsoft.PowerShell.Linux.Host/project.json +++ b/src/Microsoft.PowerShell.Linux.Host/project.json @@ -25,6 +25,8 @@ }, "content": [ + "Modules", + "PSL_profile.ps1", "types.ps1xml",