<# ##################################################################### SCRIPT GetPermissions.ps1 SYNOPSIS Gets all Servers from the domain from which the script is run in (i.e. the domain you are logged in to). Then uses the server list to query each servers Share permissions and the NTFS permissions of each share root folder. The Script creates 2 files in the same location the script is run from (sharereport.csv and ntfsreport.csv). NOTE Script requires no parameters or arguments I recommend you have the relevant permissions in the domain and on the servers being queried for optimal results. Myself or my employer do not warrantee this script in any way and use of it is entirely at the users own risk. The working functions of this script are taken from examples found at Microsoft Script Center web site and are written by Boe Prox. AUTHOR Carl Harrison The script utilises 2 functions written by Boe Prox and publically available at Microsoft Script Center. They have been altered slightly to work with this script. VERSION: 1.0 - First cut 1.1 - Sorted FQDN Ping instead of netbios ping ##################################################################### #> function Get-SharePermissions{ <# .SYNOPSIS Retrieves share permissions. This function was extracted from a Powershell Module written by Boe Prox named FileSharePermissions.psm1 .DESCRIPTION Retrieves share permissions. .PARAMETER computer Name of server to test. .EXAMPLE Get-SharePermissions -computer Test #> [cmdletbinding( DefaultParameterSetName = 'computer', ConfirmImpact = 'low' )] Param( [Parameter( Mandatory = $True, Position = 0, ParameterSetName = 'computer', ValueFromPipeline = $True)] [array]$computer ) Begin { #Process Share report $sharereport = @() } Process { #Iterate through comptuers ForEach ($c in $computer) { Try { #Write-Verbose "Computer: $($c)" #Retrieve share information from comptuer $ShareSec = Get-WmiObject -Class Win32_LogicalShareSecuritySetting -ComputerName $c -ea stop ForEach ($Shares in $sharesec) { #Write-Verbose "Share: $($Shares.name)" #Try to get the security descriptor $SecurityDescriptor = $ShareS.GetSecurityDescriptor() #Iterate through each descriptor ForEach ($DACL in $SecurityDescriptor.Descriptor.DACL) { $arrshare = New-Object PSObject $arrshare | Add-Member NoteProperty Computer $c $arrshare | Add-Member NoteProperty Name $Shares.Name $arrshare | Add-Member NoteProperty ID $DACL.Trustee.Name #Convert the current output into something more readable Switch ($DACL.AccessMask) { 2032127 {$AccessMask = "FullControl"} 1179785 {$AccessMask = "Read"} 1180063 {$AccessMask = "Read, Write"} 1179817 {$AccessMask = "ReadAndExecute"} -1610612736 {$AccessMask = "ReadAndExecuteExtended"} 1245631 {$AccessMask = "ReadAndExecute, Modify, Write"} 1180095 {$AccessMask = "ReadAndExecute, Write"} 268435456 {$AccessMask = "FullControl (Sub Only)"} default {$AccessMask = $DACL.AccessMask} } $arrshare | Add-Member NoteProperty AccessMask $AccessMask #Convert the current output into something more readable Switch ($DACL.AceType) { 0 {$AceType = "Allow"} 1 {$AceType = "Deny"} 2 {$AceType = "Audit"} } $arrshare | Add-Member NoteProperty AceType $AceType #Add to existing array $sharereport += $arrshare } } } #Catch any errors Catch { $arrshare = New-Object PSObject $arrshare | Add-Member NoteProperty Computer $c $arrshare | Add-Member NoteProperty Name "NA" $arrshare | Add-Member NoteProperty ID "NA" $arrshare | Add-Member NoteProperty AccessMask "NA" #Add to existing array $sharereport += $arrshare } Finally { #Do Nothing Currently } } } End { #Display report #$ShareReport #$ShareReport | Export-Csv -notypeinformation "sharereport.csv" return $sharereport } } function Get-ShareNTFSPermissions{ <# .SYNOPSIS Retrieves NTFS permissions on a share. This function was extracted from a Powershell Module written by Boe Prox named FileSharePermissions.psm1 .DESCRIPTION Retrieves NTFS permissions on a share. .PARAMETER computer Name of server to test. .EXAMPLE Get-ShareNTFSPermissions -computer Test #> [cmdletbinding( DefaultParameterSetName = 'computer', ConfirmImpact = 'low' )] Param( [Parameter( Mandatory = $True, Position = 0, ParameterSetName = 'computer', ValueFromPipeline = $True)] [array]$computer ) Begin { #Process NTFS Share report $ntfsreport = @() } Process { #Iterate through each computer ForEach ($c in $computer) { Try { Write-Verbose "Computer: $($c)" #Gather share information $shares = Gwmi -comp $c Win32_Share -ea stop | ? {$_.Name -ne 'ADMIN$'-AND $_.Name -ne 'C$' -AND $_.Name -ne 'IPC$'} | Select Name,Path ForEach ($share in $shares) { #Iterate through shares Write-Verbose "Share: $($share.name)" If ($share.path -ne "") { #Retrieve ACL information from Share $remoteshare = $share.path -replace ":","$" Try { #Gather NTFS security information from each share $acls = Get-ACL "\\$computer\$remoteshare" #iterate through each ACL ForEach ($acl in $acls.access) { If ($acl.FileSystemRights -match "\d") { Switch ($acl.FileSystemRights) { 2032127 {$AccessMask = "FullControl"} 1179785 {$AccessMask = "Read"} 1180063 {$AccessMask = "Read, Write"} 1179817 {$AccessMask = "ReadAndExecute"} -1610612736 {$AccessMask = "ReadAndExecuteExtended"} 1245631 {$AccessMask = "ReadAndExecute, Modify, Write"} 1180095 {$AccessMask = "ReadAndExecute, Write"} 268435456 {$AccessMask = "FullControl (Sub Only)"} default {$AccessMask = "Unknown"} } } Else { $AccessMask = $acl.FileSystemRights } $arrntfs = New-Object PSObject #Process NTFS Report $arrntfs | Add-Member NoteProperty Computer $c $arrntfs | Add-Member NoteProperty ShareName $Share.name $arrntfs | Add-Member NoteProperty Path $share.path $arrntfs | Add-Member NoteProperty NTFS_User $acl.IdentityReference $arrntfs | Add-Member NoteProperty NTFS_Rights $AccessMask $ntfsreport += $arrntfs } } Catch { $arrntfs = New-Object PSObject #Process NTFS Report $arrntfs | Add-Member NoteProperty Computer $c $arrntfs | Add-Member NoteProperty ShareName "NA" $arrntfs | Add-Member NoteProperty Path "NA" $arrntfs | Add-Member NoteProperty NTFS_User "NA" $arrntfs | Add-Member NoteProperty NTFS_Rights "NA" #Add to existing array $ntfsreport += $arrntfs } Finally { #Do nothing currently } } } } Catch { $arrntfs = New-Object PSObject $arrntfs | Add-Member NoteProperty Computer $c $arrntfs | Add-Member NoteProperty ShareName "NA" $arrntfs | Add-Member NoteProperty Path "NA" $arrntfs | Add-Member NoteProperty NTFS_User "NA" $arrntfs | Add-Member NoteProperty NTFS_Rights "NA" #Add to existing array $ntfsreport += $arrntfs } Finally { #Do Nothing Currently } } } End { #Display report #$ntfsreport #$ntfsreport | Export-Csv -notypeinformation "ntfsreport.csv" return $ntfsreport } } #THIS IS THE START OF THE SCRIPT #Define Some variables and Arrays $strOperatingSystem = "*Server*" $Servers = @() $ServersShareReport = @() $ServersNTFSReport = @() #Set up the Directory Search parameters $objDomain = New-Object System.DirectoryServices.DirectoryEntry $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objSearcher.SearchRoot = $objDomain $objSearcher.Filter = ("OperatingSystem=$strOperatingSystem") $objSearcher.PageSize = 1000 #Define the Attributes we need from the search $colProplist = "name","dnshostname","operatingsystemversion" #Do the Search foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)} $colResults = $objSearcher.FindAll() $Ping = New-Object System.Net.NetworkInformation.Ping ForEach ($objResult in $colResults) { $Server = $objResult.Properties.name $ServerDNS = $objResult.Properties.dnshostname Write-Host "Pinging $ServerDNS" $errorActionPreference="SilentlyContinue" $Pingy = $ping.send($ServerDNS,5000) $ServerShareOutput = $Null $ServerNTFSOutput = $Null Try { #This is where we go get the information If ($Pingy.status.tostring() –eq “Success”) { #Cool we can get to the server now lets gather some information write-host “$Server Available” $errorActionPreference="Continue" $ServerShareOutput = Get-SharePermissions -computer $ServerDNS $ServerNTFSOutput = Get-ShareNTFSPermissions -computer $ServerDNS $ServersShareReport += $ServerShareOutput $ServersNTFSReport += $ServerNTFSOutput } else { #oh-oh either WMI is restricted or we cannot get to the current server write-host “$Server Not Available" $FailedShareServer = New-Object PSObject $FailedShareServer | Add-Member NoteProperty Computer "$Server" $FailedShareServer | Add-Member NoteProperty Name "Server No Available" $ServersShareReport += $FailedShareServer $FailedNTFSServer = New-Object PSObject $FailedNTFSServer | Add-Member NoteProperty Computer "$Server" $FailedNTFSServer | Add-Member NoteProperty ShareName "Server No Available" $ServersNTFSReport += $FailedNTFSServer } } Catch { #And this just catches any weird error events write-host “$Server Not Available" $FailedShareServer = New-Object PSObject $FailedShareServer | Add-Member NoteProperty Computer "$Server" $FailedShareServer | Add-Member NoteProperty Name "Server Not Available" $ServersShareReport += $FailedShareServer $FailedNTFSServer = New-Object PSObject $FailedNTFSServer | Add-Member NoteProperty Computer "$Server" $FailedNTFSServer | Add-Member NoteProperty ShareName "Server Not Available" $ServersNTFSReport += $FailedNTFSServer } Finally { $errorActionPreference="Continue" $pingy = $null $Server = $Null } } #Now we have the data let's save it to file - in the same location the script is run from $ServersShareReport | Export-Csv -notypeinformation ".\sharereport.csv" $ServersShareReport = @() $ServersNTFSReport | Export-Csv -notypeinformation ".\ntfsreport.csv" $ServersNTFSReport = @()