208 lines
7.3 KiB
PowerShell
208 lines
7.3 KiB
PowerShell
# Wrapper around Write-Host, but surrounds the string with delimiters so that we can disregard spam output originating from RemoteExchange scripts
|
|
function Write-Output ( [string] $string ) {
|
|
$string = [string]::join("<br>",($string.Split("`r`n")))
|
|
# <output> is a placeholder delimiter, it is later replaced by the Ruby script
|
|
Write-Host "<output>$string</output>"
|
|
}
|
|
|
|
function Export-Mailboxes ([string] $mailbox, [string] $filter, [string] $path) {
|
|
# $path may arrive as a short path (C:\Users\ADMINI~1\...), but Exchange does not accept short paths.
|
|
# Get-Item is used to translate the short path to a full path.
|
|
$path_parent = Split-Path -Path $path -Parent
|
|
$path_leaf = Split-Path -Path $path -Leaf
|
|
$path_parent_full = (Get-Item -LiteralPath $path_parent).FullName
|
|
$path_full = Join-Path $path_parent_full $path_leaf
|
|
|
|
# Convert path to a UNC path
|
|
$path_drive = (Split-Path -Path $path_full -Qualifier)[0]
|
|
$path_rest = Split-Path -Path $path_full -NoQualifier
|
|
$unc_path = '\\localhost\' + $path_drive + '$' + $path_rest
|
|
|
|
Write-Output "Exporting mailbox..."
|
|
|
|
try {
|
|
if ($filter -eq "") {
|
|
# Don't use a filter
|
|
$export_req = New-MailboxExportRequest -Priority High -Mailbox $mailbox -FilePath $unc_path
|
|
} else {
|
|
# Use a filter
|
|
$export_req = New-MailboxExportRequest -Priority High -ContentFilter $filter -Mailbox $mailbox -FilePath $unc_path
|
|
}
|
|
}
|
|
catch {
|
|
$EM = $_.Exception.Message
|
|
Write-Output "Error exporting mailbox - New-MailboxExportRequest failed"
|
|
Write-Output "Exception message: '$EM'"
|
|
return
|
|
}
|
|
|
|
if ($export_req -eq $null) {
|
|
Write-Output "Error exporting mailbox - New-MailboxExportRequest returned null"
|
|
return
|
|
}
|
|
|
|
# Monitor the export job status
|
|
While ($true) {
|
|
$req_status = $export_req | Get-MailboxExportRequest
|
|
|
|
Write-Output ". $($req_status.Status)"
|
|
|
|
if ($req_status.Status -eq "Failed") {
|
|
Write-Output "Error exporting mailbox - Export job failed"
|
|
break
|
|
}
|
|
|
|
if ($req_status.Status -eq "Completed") {
|
|
Write-Output "Exporting done"
|
|
break
|
|
}
|
|
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
|
|
$export_req | Remove-MailboxExportRequest -Confirm:$false
|
|
}
|
|
|
|
function List-Mailboxes {
|
|
# Don't throw exceptions when errors are encountered
|
|
$Global:ErrorActionPreference = "Continue"
|
|
|
|
$servers = Get-MailboxServer
|
|
foreach ($server in $servers) {
|
|
Write-Output "----------"
|
|
Write-Output "Server:"
|
|
Write-Output "- Name: $($server.Name)"
|
|
Write-Output "- Version: $($server.AdminDisplayVersion)"
|
|
Write-Output "- Role: $($server.ServerRole)"
|
|
Write-Output "-----"
|
|
Write-Output "Mailboxes:"
|
|
$mailboxes = Get-Mailbox -Server $server
|
|
foreach ($mailbox in $mailboxes) {
|
|
Write-Output "---"
|
|
Write-Output "- Display Name: $($mailbox.DisplayName)"
|
|
Write-Output "- Email Addresses: $($mailbox.EmailAddresses)"
|
|
Write-Output "- Creation date: $($mailbox.WhenMailboxCreated)"
|
|
Write-Output "- Address list membership: $($mailbox.AddressListMembership)"
|
|
|
|
$folderstats = $mailbox | Get-MailboxFolderStatistics -IncludeOldestAndNewestItems -IncludeAnalysis
|
|
if ($folderstats) {
|
|
$non_empty_folders = ( $folderstats | ? {$_.ItemsInFolder -gt 0 })
|
|
if (!($non_empty_folders)) {
|
|
Write-Output "- (All folders are empty)"
|
|
} else {
|
|
Write-Output "- Folders:"
|
|
foreach ($folderstats in $non_empty_folders) {
|
|
$output_string = "-- Path $($folderstats.FolderPath), Items $($folderstats.ItemsInFolder), Size $($folderstats.FolderSize)"
|
|
if ($folderstats.NewestItemReceivedDate) {
|
|
$output_string += ", Newest received date $($folderstats.NewestItemReceivedDate)"
|
|
}
|
|
Write-Output "$output_string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Ensure-Role ([string] $user, [string] $role) {
|
|
$assignments = Get-ManagementRoleAssignment -Role $role -RoleAssignee $user -Delegating $false
|
|
if (!($assignments)) {
|
|
Write-Output "User not assigned to role $role - Assigning now"
|
|
New-ManagementRoleAssignment -Role $role -User $user
|
|
}
|
|
}
|
|
|
|
function Check-Permission {
|
|
try {
|
|
$Current_Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$Groups = Get-ADPrincipalGroupMembership -identity $Current_Identity.User
|
|
}
|
|
catch {
|
|
$EM = $_.Exception.Message
|
|
Write-Output "Error getting the current user's Active Directory group membership"
|
|
Write-Output "Exception message: '$EM'"
|
|
return $false
|
|
}
|
|
|
|
return [bool] ( $Groups | ? {$_.samAccountName -eq "Organization Management" })
|
|
}
|
|
|
|
function Assign-Roles {
|
|
$Current_Username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
|
|
|
# Ensure the current user has the following roles, required for the New-MailboxExportRequest cmdlet
|
|
Ensure-Role $Current_Username "Mailbox Search"
|
|
Ensure-Role $Current_Username "Mailbox Import Export"
|
|
}
|
|
|
|
function Get-RemoteExchangePath {
|
|
# Get the path of the RemoteExchange.ps1 script
|
|
$Path = $env:ExchangeInstallPath
|
|
if (!$Path -Or !(Test-Path $Path)) {
|
|
$Path = Join-Path $env:ProgramFiles 'Microsoft\Exchange Server\V15\'
|
|
if (!(Test-Path $Path)) {
|
|
$Path = Join-Path $env:ProgramFiles 'Microsoft\Exchange Server\V14\'
|
|
if (!(Test-Path $Path)) {
|
|
return $null
|
|
}
|
|
}
|
|
}
|
|
|
|
$RemoteExchangePath = Join-Path $Path 'Bin\RemoteExchange.ps1'
|
|
if (!(Test-Path $RemoteExchangePath)) {
|
|
return $null
|
|
}
|
|
|
|
return $RemoteExchangePath
|
|
}
|
|
|
|
# Need to set this in order to catch errors raised by RemoteExchange as exceptions
|
|
$Global:ErrorActionPreference = "Stop"
|
|
|
|
$RemoteExchangePath = Get-RemoteExchangePath
|
|
if (!($RemoteExchangePath)) {
|
|
Write-Output "Couldn't find RemoteExchange PowerShell script"
|
|
return
|
|
}
|
|
|
|
try {
|
|
Import-Module $RemoteExchangePath
|
|
}
|
|
catch {
|
|
$EM = $_.Exception.Message
|
|
Write-Output "Error loading the RemoteExchange PowerShell script"
|
|
Write-Output "Exception message: '$EM'"
|
|
return
|
|
}
|
|
|
|
try {
|
|
Connect-ExchangeServer -auto
|
|
}
|
|
catch {
|
|
$EM = $_.Exception.Message
|
|
Write-Output "Error connecting to Exchange server"
|
|
Write-Output "Exception message: '$EM'"
|
|
return
|
|
}
|
|
|
|
try {
|
|
# There's a bug in Exchange 2010 that requires running an Exchange cmdlet before an AD cmdlet, otherwise the script won't work.
|
|
# For this reason, we run Get-Mailbox here and disregard its output.
|
|
Get-Mailbox | Out-Null
|
|
|
|
if (!(Check-Permission)) {
|
|
Write-Output "Permission check failed, current user must be assigned to the Organization Management role group"
|
|
return
|
|
}
|
|
|
|
_COMMAND_
|
|
}
|
|
catch [System.Management.Automation.CommandNotFoundException] {
|
|
Write-Output "A CommandNotFoundException was thrown - Some Exchange Management Shell are unavailable. This is most likely due to insufficient credentials in meterpreter session"
|
|
}
|
|
catch {
|
|
$EM = $_.Exception.Message
|
|
Write-Output "Aborting, caught an exception"
|
|
Write-Output "Exception message: '$EM'"
|
|
}
|