7DWSM.ps1
function Confirm-PoSHAdminPrivileges { <# .SYNOPSIS Function to test administrative privileges .EXAMPLE Confirm-PoSHAdminPrivileges #> $User = [Security.Principal.WindowsIdentity]::GetCurrent() if((New-Object Security.Principal.WindowsPrincipal $User).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)) { $Result = "Validated" } $Result } function Confirm-PoSHServerIP { <# .SYNOPSIS Function to verify IP address on server .EXAMPLE Confirm-PoSHServerIP -IP "192.168.2.1" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'IP address')] [string]$IP ) # Get Networking Adapter Configuration $IPConfigs = Get-WmiObject Win32_NetworkAdapterConfiguration # Get All IP Addresses foreach ($IPConfig in $IPConfigs) { if ($IPConfig.IPaddress) { foreach ($IPAddress in $IPConfig.IPaddress) { if ("$IP" -eq "$IPAddress") { $Result = "Validated" } } } } $Result } function Get-DirectoryContent { <# .SYNOPSIS Function to get directory content .EXAMPLE Get-DirectoryContent -Path "C:\" -HeaderName "poshserver.net" -RequestURL "http://poshserver.net" -SubfolderName "/" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'Directory Path')] [string]$Path, [Parameter( Mandatory = $false, HelpMessage = 'Header Name')] [string]$HeaderName, [Parameter( Mandatory = $false, HelpMessage = 'Request URL')] [string]$RequestURL, [Parameter( Mandatory = $false, HelpMessage = 'Subfolder Name')] [string]$SubfolderName ) @" <html> <head> <title>$($HeaderName)</title> </head> <body> <h1>$($HeaderName) - $($SubfolderName)</h1> <hr> "@ $ParentDirectory = $RequestURL + $Subfoldername + "../" @" <a href="$($ParentDirectory)">[To Parent Directory]</a><br><br> <table cellpadding="5"> "@ $Files = (Get-ChildItem "$Path") foreach ($File in $Files) { $FileURL = $RequestURL + $Subfoldername + $File.Name if (!$File.Length) { $FileLength = "[dir]" } else { $FileLength = $File.Length } @" <tr> <td align="right">$($File.LastWriteTime)</td> <td align="right">$($FileLength)</td> <td align="left"><a href="$($FileURL)">$($File.Name)</a></td> </tr> "@ } @" </table> <hr> </body> </html> "@ } function New-PoSHLogHash { <# .SYNOPSIS Function to hash PoSHServer log file .EXAMPLE New-PoSHLogHash -LogSchedule "Hourly" -LogDirectory "C:\inetpub\logs" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'Log Schedule')] [string]$LogSchedule, [Parameter( Mandatory = $true, HelpMessage = 'Log Directory Path')] [string]$LogDirectory, [Parameter( Mandatory = $false, HelpMessage = 'Debug Mode')] $DebugMode = $false ) if ($LogSchedule -eq "Hourly") { $LogNameFormatLastHour = (Get-Date).AddHours(-1).ToString("yyMMddHH") $LogFileNameLastHour = "u_ex" + $LogNameFormatLastHour + ".log" $LogFilePathLastHour = $LogDirectory + "\" + $LogFileNameLastHour $SigFileName = "u_ex" + $LogNameFormatLastHour + ".sign" $SigFilePath = $LogDirectory + "\" + $SigFileName $DateFileName = "u_ex" + $LogNameFormatLastHour + ".date" $DateFilePath = $LogDirectory + "\" + $DateFileName $LastLogFilePath = $LogFilePathLastHour } else { $LogNameFormatYesterday = (Get-Date).AddDays(-1).ToString("yyMMdd") $LogFileNameYesterday = "u_ex" + $LogNameFormatYesterday + ".log" $LogFilePathYesterday = $LogDirectory + "\" + $LogFileNameYesterday $SigFileName = "u_ex" + $LogNameFormatYesterday + ".sign" $SigFilePath = $LogDirectory + "\" + $SigFileName $DateFileName = "u_ex" + $LogNameFormatYesterday + ".date" $DateFilePath = $LogDirectory + "\" + $DateFileName $LastLogFilePath = $LogFilePathYesterday } if ([System.IO.File]::Exists($LastLogFilePath)) { if (![System.IO.File]::Exists($SigFilePath)) { $LogHashJobArgs = @($LastLogFilePath,$SigFilePath,$DateFilePath) try { $LogHashJob = Start-Job -ScriptBlock { param ($LastLogFilePath, $SigFilePath, $DateFilePath) if (![System.IO.File]::Exists($DateFilePath)) { $HashAlgorithm = "MD5" $HashType = [Type] "System.Security.Cryptography.$HashAlgorithm" $Hasher = $HashType::Create() $DateString = Get-Date -uformat "%d.%m.%Y" $TimeString = (w32tm /stripchart /computer:time.ume.tubitak.gov.tr /samples:1)[-1].split("")[0] $DateString = $DateString + " " + $TimeString $InputStream = New-Object IO.StreamReader $LastLogFilePath $HashBytes = $Hasher.ComputeHash($InputStream.BaseStream) $InputStream.Close() $Builder = New-Object System.Text.StringBuilder $HashBytes | Foreach-Object { [void] $Builder.Append($_.ToString("X2")) } $HashString = $Builder.ToString() $HashString = $HashString + " " + $DateString $Stream = [System.IO.StreamWriter]$SigFilePath $Stream.Write($HashString) $Stream.Close() $Stream = [System.IO.StreamWriter]$DateFilePath $Stream.Write($DateString) $Stream.Close() $InputStream = New-Object IO.StreamReader $SigFilePath $HashBytes = $Hasher.ComputeHash($InputStream.BaseStream) $InputStream.Close() $Builder = New-Object System.Text.StringBuilder $HashBytes | Foreach-Object { [void] $Builder.Append($_.ToString("X2")) } $HashString = $Builder.ToString() $Stream = [System.IO.StreamWriter]$SigFilePath $Stream.Write($HashString) $Stream.Close() } } -ArgumentList $LogHashJobArgs } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } else { Add-Content -Value "Could not find log file." -Path "$LogDirectory\debug.txt" } } function Start-PoSHLogParser { <# .SYNOPSIS Function to parse PoSHServer log files .EXAMPLE Start-PoSHLogParser -LogPath "C:\inetpub\logs\hourly.log" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'Log Path')] [string]$LogPath ) $File = $LogPath $Log = Get-Content $File | where {$_ -notLike "#[D,S-V]*" } $Columns = (($Log[0].TrimEnd()) -replace "#Fields: ", "" -replace "-","" -replace "\(","" -replace "\)","").Split(" ") $Count = $Columns.Length $Rows = $Log | where {$_ -notLike "#Fields"} $IISLog = New-Object System.Data.DataTable "IISLog" foreach ($Column in $Columns) { $NewColumn = New-Object System.Data.DataColumn $Column, ([string]) $IISLog.Columns.Add($NewColumn) } foreach ($Row in $Rows) { $Row = $Row.Split(" ") $AddRow = $IISLog.newrow() for($i=0;$i -lt $Count; $i++) { $ColumnName = $Columns[$i] $AddRow.$ColumnName = $Row[$i] } $IISLog.Rows.Add($AddRow) } $IISLog } function Get-MimeType { <# .SYNOPSIS Function to get mime types .EXAMPLE Get-MimeType -Extension ".jpg" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'Extension')] [string]$Extension ) switch ($Extension) { .ps1 {"text/ps1"} .psxml {"text/psxml"} .psapi {"text/psxml"} .posh {"text/psxml"} .html {"text/html"} .htm {"text/html"} .php {"text/php"} .css {"text/css"} .jpeg {"image/jpeg"} .jpg {"image/jpeg"} .gif {"image/gif"} .ico {"image/x-icon"} .flv {"video/x-flv"} .swf {"application/x-shockwave-flash"} .js {"text/javascript"} .txt {"text/plain"} .rar {"application/octet-stream"} .zip {"application/x-zip-compressed"} .rss {"application/rss+xml"} .xml {"text/xml"} .pdf {"application/pdf"} .png {"image/png"} .mpg {"video/mpeg"} .mpeg {"video/mpeg"} .mp3 {"audio/mpeg"} .oga {"audio/ogg"} .spx {"audio/ogg"} .mp4 {"video/mp4"} .m4v {"video/m4v"} .ogg {"video/ogg"} .ogv {"video/ogg"} .webm {"video/webm"} .wmv {"video/x-ms-wmv"} .woff {"application/x-font-woff"} .eot {"application/vnd.ms-fontobject"} .svg {"image/svg+xml"} .svgz {"image/svg+xml"} .otf {"font/otf"} .ttf {"application/x-font-ttf"} .xht {"application/xhtml+xml"} .xhtml {"application/xhtml+xml"} default {"text/html"} } } function Set-PHPEncoding { param ($PHPOutput) $EncodingFix = [string]$PHPOutput $EncodingFix = $EncodingFix.Replace("─▒","ı") $EncodingFix = $EncodingFix.Replace("─░","İ") $EncodingFix = $EncodingFix.Replace("┼ş","ş") $EncodingFix = $EncodingFix.Replace("┼Ş","Ş") $EncodingFix = $EncodingFix.Replace("─ş","ğ") $EncodingFix = $EncodingFix.Replace("─Ş","Ğ") $EncodingFix = $EncodingFix.Replace("├ğ","ç") $EncodingFix = $EncodingFix.Replace("├ç","Ç") $EncodingFix = $EncodingFix.Replace("├╝","ü") $EncodingFix = $EncodingFix.Replace("├£","Ü") $EncodingFix = $EncodingFix.Replace("├Â","ö") $EncodingFix = $EncodingFix.Replace("├û","Ö") $EncodingFix = $EncodingFix.Replace("ÔÇô","'") $EncodingFix } function Get-PoSHPHPContent { <# .SYNOPSIS Function to get php content .EXAMPLE Get-PoSHPHPContent -PHPCgiPath "C:\php.exe" -File "C:\test.php" -PoSHPHPGET "test=value" .EXAMPLE Get-PoSHPHPContent -PHPCgiPath "C:\php.exe" -File "C:\test.php" -PoSHPHPPOST "test=value" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'PHP-Cgi Path')] [string]$PHPCgiPath, [Parameter( Mandatory = $true, HelpMessage = 'File Path')] [string]$File, [Parameter( Mandatory = $false, HelpMessage = 'PHP GET String')] [string]$PoSHPHPGET, [Parameter( Mandatory = $false, HelpMessage = 'PHP POST String')] [string]$PoSHPHPPOST ) # Set PHP Environment $env:GATEWAY_INTERFACE="CGI/1.1" $env:SCRIPT_FILENAME="$File" $env:REDIRECT_STATUS="200" $env:SERVER_PROTOCOL="HTTP/1.1" $env:HTTP_ACCEPT="text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" $env:CONTENT_TYPE="application/x-www-form-urlencoded" if ($PoSHPHPPOST) { # Set PHP POST Environment $env:REQUEST_METHOD="POST" $PHP_CONTENT_LENGTH = $PoSHPHPPOST.Length $env:CONTENT_LENGTH="$PHP_CONTENT_LENGTH" # Get PHP Content $PHPOutput = "$PoSHPHPPOST" | &$PHPCgiPath } else { # Set PHP GET Environment $env:REQUEST_METHOD="GET" $env:QUERY_STRING="$PoSHPHPGET" # Get PHP Content $PHPOutput = &$PHPCgiPath } # Get PHP Header Line Number $PHPHeaderLineNumber = ($PHPOutput | Select-String -Pattern "^$")[0].LineNumber # Get PHP Header $PHPHeader = $PHPOutput | Select -First $PHPHeaderLineNumber # Get Redirection Location $GetPHPLocation = $PHPHeader | Select-String "Location:" # Check Redirection Location if ($GetPHPLocation) { $GetPHPLocation = $GetPHPLocation -match 'Location: (.*)/?' if ($GetPHPLocation -eq $True) { $PHPRedirectionURL = $Matches[1] } else { $PHPRedirectionURL = $Null; } } # Redirect to Location if ($PHPRedirectionURL) { # Redirection Output $PHPRedirection = '<html>' $PHPRedirection += '<script type="text/javascript">' $PHPRedirection += 'window.location = "' + $PHPRedirectionURL + '"' $PHPRedirection += '</script>' $PHPRedirection += '</html>' $PHPRedirection } else { # Output PHP Content $PHPOutput = $PHPOutput | Select -Skip $PHPHeaderLineNumber $PHPOutput } } function Get-PoSHPostStream { <# .SYNOPSIS Function to get php post stream .EXAMPLE Get-PoSHPostStream -InputStream $InputStream -ContentEncoding $ContentEncoding #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $true, HelpMessage = 'Input Stream')] $InputStream, [Parameter( Mandatory = $true, HelpMessage = 'Content Encoding')] $ContentEncoding ) $PoSHCommand = New-Object IO.StreamReader ($InputStream,$ContentEncoding) $PoSHCommand = $PoSHCommand.ReadToEnd() $PoSHCommand = $PoSHCommand.ToString() if ($PoSHCommand) { $PoSHCommand = $PoSHCommand.Replace("+"," ") $PoSHCommand = $PoSHCommand.Replace("%20"," ") $PoSHCommand = $PoSHCommand.Replace("%21","!") $PoSHCommand = $PoSHCommand.Replace('%22','"') $PoSHCommand = $PoSHCommand.Replace("%23","#") $PoSHCommand = $PoSHCommand.Replace("%24","$") $PoSHCommand = $PoSHCommand.Replace("%25","%") $PoSHCommand = $PoSHCommand.Replace("%27","'") $PoSHCommand = $PoSHCommand.Replace("%28","(") $PoSHCommand = $PoSHCommand.Replace("%29",")") $PoSHCommand = $PoSHCommand.Replace("%2A","*") $PoSHCommand = $PoSHCommand.Replace("%2B","+") $PoSHCommand = $PoSHCommand.Replace("%2C",",") $PoSHCommand = $PoSHCommand.Replace("%2D","-") $PoSHCommand = $PoSHCommand.Replace("%2E",".") $PoSHCommand = $PoSHCommand.Replace("%2F","/") $PoSHCommand = $PoSHCommand.Replace("%3A",":") $PoSHCommand = $PoSHCommand.Replace("%3B",";") $PoSHCommand = $PoSHCommand.Replace("%3C","<") $PoSHCommand = $PoSHCommand.Replace("%3E",">") $PoSHCommand = $PoSHCommand.Replace("%3F","?") $PoSHCommand = $PoSHCommand.Replace("%5B","[") $PoSHCommand = $PoSHCommand.Replace("%5C","\") $PoSHCommand = $PoSHCommand.Replace("%5D","]") $PoSHCommand = $PoSHCommand.Replace("%5E","^") $PoSHCommand = $PoSHCommand.Replace("%5F","_") $PoSHCommand = $PoSHCommand.Replace("%7B","{") $PoSHCommand = $PoSHCommand.Replace("%7C","|") $PoSHCommand = $PoSHCommand.Replace("%7D","}") $PoSHCommand = $PoSHCommand.Replace("%7E","~") $PoSHCommand = $PoSHCommand.Replace("%7F","_") $PoSHCommand = $PoSHCommand.Replace("%7F%25","%") $PoSHPostStream = $PoSHCommand $PoSHCommand = $PoSHCommand.Split("&") $Properties = New-Object Psobject $Properties | Add-Member Noteproperty PoSHPostStream $PoSHPostStream foreach ($Post in $PoSHCommand) { $PostValue = $Post.Replace("%26","&") $PostContent = $PostValue.Split("=") $PostName = $PostContent[0].Replace("%3D","=") $PostValue = $PostContent[1].Replace("%3D","=") if ($PostName.EndsWith("[]")) { $PostName = $PostName.Substring(0,$PostName.Length-2) if (!(New-Object PSObject -Property @{PostName=@()}).PostName) { $Properties | Add-Member NoteProperty $Postname (@()) $Properties."$PostName" += $PostValue } else { $Properties."$PostName" += $PostValue } } else { $Properties | Add-Member NoteProperty $PostName $PostValue } } Write-Output $Properties } } function Get-PoSHQueryString { <# .SYNOPSIS Function to get query string .EXAMPLE Get-PoSHQueryString -Request $Request #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'Request')] $Request ) if ($Request) { $PoSHQueryString = $Request.RawUrl.Split("?")[1] $QueryStrings = $Request.QueryString $Properties = New-Object Psobject $Properties | Add-Member Noteproperty PoSHQueryString $PoSHQueryString foreach ($Query in $QueryStrings) { $QueryString = $Request.QueryString["$Query"] if ($QueryString -and $Query) { $Properties | Add-Member Noteproperty $Query $QueryString } } Write-Output $Properties } } function Get-PoSHWelcomeBanner { <# .SYNOPSIS Function to get welcome banner .EXAMPLE Get-PoSHWelcomeBanner -Hostname "localhost" -Port "8080" -SSL $True -SSLIP "10.10.10.2" -SSLPort "8443" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'IP Address or Hostname')] [Alias('IP')] [string]$Hostname, [Parameter( Mandatory = $false, HelpMessage = 'Port Number')] [string]$Port, [Parameter( Mandatory = $false, HelpMessage = 'Enable SSL')] $SSL = $false, [Parameter( Mandatory = $false, HelpMessage = 'SSL IP Address')] [string]$SSLIP, [Parameter( Mandatory = $false, HelpMessage = 'SSL Port Number')] [string]$SSLPort, [Parameter( Mandatory = $false, HelpMessage = 'Debug Mode')] $DebugMode = $false ) # Get Hostname if (!$Hostname -or $Hostname -eq "+") { $Hostname = "localhost" } else { $Hostname = @($Hostname.Split(","))[0] } # Get Port if ($Port -ne "80") { $Port = ":$Port" } else { $Port = $null } if ($SSL) { # Get SSL Hostname if (!$SSLIP -or $SSLIP -eq "+") { $SSLIP = "localhost" } else { $SSLIP = @($SSLIP.Split(","))[0] } # Get SSL Port if ($SSLPort -eq "443") { $SSLPort = "/" } else { $SSLPort = ":$SSLPort" } } if (!$DebugMode) { clear } Write-Host " " Write-Host " Welcome to PoSH Server" Write-Host " " Write-Host " " Write-Host " You can start browsing your webpage from:" Write-Host " http://$Hostname$Port" if ($SSL) { if ($SSLPort -eq "/") { Write-Host " https://$SSLIP" } else { Write-Host " https://$SSLIP$SSLPort" } } Write-Host " " Write-Host " " Write-Host " Thanks for using PoSH Server.." Write-Host " " Write-Host " " Write-Host " " } function New-PoSHAPIXML { <# .SYNOPSIS Function to create PoSHAPI XML .EXAMPLE New-PoSHAPIXML -ResultCode "1" -ResultMessage "Service unavailable" -RootTag "Result" -ItemTag "OperationResult" -Details #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'Result Code')] $ResultCode = "-1", [Parameter( Mandatory = $false, HelpMessage = 'Result Message')] $ResultMessage = "The operation failed", [Parameter( Mandatory = $false, HelpMessage = 'Root Tag')] $RootTag = "Result", [Parameter( Mandatory = $false, HelpMessage = 'Item Tag')] $ItemTag = "OperationResult", [Parameter( Mandatory = $false, HelpMessage = 'Child Items')] $ChildItems = "*", [Parameter( Mandatory = $false, HelpMessage = 'Attributes')] $Attributes = $Null, [Parameter( Mandatory = $false, HelpMessage = 'Details')] $Details = $false ) Begin { $xml = "<?xml version=""1.0"" encoding=""utf-8""?>`n" $xml += "<$RootTag>`n" $xml += " <Code>$ResultCode</Code>`n" $xml += " <Message>$ResultMessage</Message>`n" } Process { if ($Details) { $xml += " <$ItemTag" if ($Attributes) { foreach ($attr in $_ | Get-Member -type *Property $attributes) { $name = $attr.Name $xml += " $Name=`"$($_.$Name)`"" } } $xml += ">`n" foreach ($child in $_ | Get-Member -Type *Property $childItems) { $name = $child.Name $xml += " <$Name>$($_.$Name)</$Name>`n" } $xml += " </$ItemTag>`n" } } End { $xml += "</$RootTag>`n" $xml } } function Request-PoSHCertificate { <# .SYNOPSIS Function to create PoSH Certificate request .EXAMPLE Request-PoSHCertificate #> $SSLSubject = "PoSHServer" $SSLName = New-Object -com "X509Enrollment.CX500DistinguishedName.1" $SSLName.Encode("CN=$SSLSubject", 0) $SSLKey = New-Object -com "X509Enrollment.CX509PrivateKey.1" $SSLKey.ProviderName = "Microsoft RSA SChannel Cryptographic Provider" $SSLKey.KeySpec = 1 $SSLKey.Length = 2048 $SSLKey.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" $SSLKey.MachineContext = 1 $SSLKey.ExportPolicy = 1 $SSLKey.Create() $SSLObjectId = New-Object -com "X509Enrollment.CObjectIds.1" $SSLServerId = New-Object -com "X509Enrollment.CObjectId.1" $SSLServerId.InitializeFromValue("1.3.6.1.5.5.7.3.1") $SSLObjectId.add($SSLServerId) $SSLExtensions = New-Object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" $SSLExtensions.InitializeEncode($SSLObjectId) $SSLCert = New-Object -com "X509Enrollment.CX509CertificateRequestCertificate.1" $SSLCert.InitializeFromPrivateKey(2, $SSLKey, "") $SSLCert.Subject = $SSLName $SSLCert.Issuer = $SSLCert.Subject $SSLCert.NotBefore = Get-Date $SSLCert.NotAfter = $SSLCert.NotBefore.AddDays(1825) $SSLCert.X509Extensions.Add($SSLExtensions) $SSLCert.Encode() $SSLEnrollment = New-Object -com "X509Enrollment.CX509Enrollment.1" $SSLEnrollment.InitializeFromRequest($SSLCert) $SSLEnrollment.CertificateFriendlyName = 'PoSHServer SSL Certificate' $SSLCertdata = $SSLEnrollment.CreateRequest(0) $SSLEnrollment.InstallResponse(2, $SSLCertdata, 0, "") } function Register-PoSHCertificate { <# .SYNOPSIS Function to register PoSH Certificate .EXAMPLE Register-PoSHCertificate -SSLIP "10.10.10.2" -SSLPort "8443" -Thumbprint "45F53D35AB630198F19A27931283" #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'SSL IP Address')] [string]$SSLIP, [Parameter( Mandatory = $false, HelpMessage = 'SSL Port Number')] [string]$SSLPort, [Parameter( Mandatory = $false, HelpMessage = 'SSL Thumbprint')] $Thumbprint, [Parameter( Mandatory = $false, HelpMessage = 'Debug Mode')] $DebugMode = $false ) $SSLIPAddresses = @($SSLIP.Split(",")) foreach ($SSLIPAddress in $SSLIPAddresses) { $IPPort = $SSLIPAddress + ":" + $SSLPort if ($DebugMode) { # Remove Previous SSL Bindings netsh http delete sslcert ipport="$IPPort" # Add SSL Certificate netsh http add sslcert ipport="$IPPort" certhash="$Thumbprint" appid="{00112233-4455-6677-8899-AABBCCDDEEFF}" } else { # Remove Previous SSL Bindings netsh http delete sslcert ipport="$IPPort" | Out-Null # Add SSL Certificate netsh http add sslcert ipport="$IPPort" certhash="$Thumbprint" appid="{00112233-4455-6677-8899-AABBCCDDEEFF}" | Out-Null } } } function New-PoSHTimeStamp { <# .SYNOPSIS Function to generate time stamp .EXAMPLE New-PoSHTimeStamp #> $now = Get-Date $hr = $now.Hour.ToString() $mi = $now.Minute.ToString() $sd = $now.Second.ToString() $ms = $now.Millisecond.ToString() Write-Output $hr$mi$sd$ms } function Invoke-AsyncHTTPRequest { <# .SYNOPSIS Function to invoke async HTTP request .EXAMPLE Invoke-AsyncHTTPRequest #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter( Mandatory = $false, HelpMessage = 'Script Block')] $ScriptBlock, [Parameter( Mandatory = $false, HelpMessage = 'Listener')] $Listener, [Parameter( Mandatory = $false, HelpMessage = 'Hostname')] $Hostname, [Parameter( Mandatory = $false, HelpMessage = 'Hostnames')] $Hostnames, [Parameter( Mandatory = $false, HelpMessage = 'Home Directory. Example: C:\inetpub\wwwroot')] [string]$HomeDirectory, [Parameter( Mandatory = $false, HelpMessage = 'Log Directory. Example: C:\inetpub\wwwroot')] [string]$LogDirectory, [Parameter( Mandatory = $false, HelpMessage = 'PoSHServer Module Path')] [string]$PoSHModulePath, [Parameter( Mandatory = $false, HelpMessage = 'Custom Child Config Path')] [string]$CustomChildConfig, [Parameter( Mandatory = $false, HelpMessage = 'Debug Mode')] [switch]$DebugMode = $false ) $Pipeline = [System.Management.Automation.PowerShell]::Create() $Pipeline.AddScript($ScriptBlock) $Pipeline.AddArgument($Listener) $Pipeline.AddArgument($Hostname) $Pipeline.AddArgument($Hostnames) $Pipeline.AddArgument($HomeDirectory) $Pipeline.AddArgument($LogDirectory) $Pipeline.AddArgument($PoSHModulePath) $Pipeline.AddArgument($CustomChildConfig) $Pipeline.AddArgument($DebugMode) $Pipeline.BeginInvoke() } function Start-7DWSMServer { <# .SYNOPSIS Powershell Web Server to serve HTML and Powershell web contents. .DESCRIPTION Listens a port to serve web content. Supports HTML and Powershell. .PARAMETER WhatIf Display what would happen if you would run the function with given parameters. .PARAMETER Confirm Prompts for confirmation for each operation. Allow user to specify Yes/No to all option to stop prompting. .EXAMPLE Start-PoSHServer -IP 127.0.0.1 -Port 8080 .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 -asJob .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 -SSL -SSLPort 8443 -asJob .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 -SSL -SSLIP "127.0.0.1" -SSLPort 8443 -asJob .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 -DebugMode .EXAMPLE Start-PoSHServer -Hostname "poshserver.net,www.poshserver.net" -Port 8080 .EXAMPLE Start-PoSHServer -Hostname "poshserver.net,www.poshserver.net" -Port 8080 -HomeDirectory "C:\inetpub\wwwroot" .EXAMPLE Start-PoSHServer -Hostname "poshserver.net,www.poshserver.net" -Port 8080 -HomeDirectory "C:\inetpub\wwwroot" -LogDirectory "C:\inetpub\wwwroot" .EXAMPLE Start-PoSHServer -Hostname "poshserver.net" -Port 8080 -CustomConfig "C:\inetpub\DefaultConfig.ps1" -CustomJob "C:\inetpub\job.ps1" .INPUTS None .OUTPUTS None .NOTES Author: Yusuf Ozturk Website: http://www.yusufozturk.info Email: yusuf.ozturk@outlook.com Date created: 09-Oct-2011 Last modified: 07-Apr-2014 Version: 3.7 .LINK http://www.poshserver.net #> [CmdletBinding(SupportsShouldProcess = $true)] param ( # Hostname [Parameter( Mandatory = $false, HelpMessage = 'IP Address or Hostname')] [Alias('IP')] [string]$Hostname, # Port Number [Parameter( Mandatory = $false, HelpMessage = 'Port Number')] [string]$Port, # SSL IP Address [Parameter( Mandatory = $false, HelpMessage = 'SSL IP Address')] [string]$SSLIP, # SSL Port Number [Parameter( Mandatory = $false, HelpMessage = 'SSL Port Number')] [string]$SSLPort, # SSL Port Number [Parameter( Mandatory = $false, HelpMessage = 'SSL Friendly Name. Example: poshserver.net')] [string]$SSLName, # Home Directory [Parameter( Mandatory = $false, HelpMessage = 'Home Directory. Example: C:\inetpub\wwwroot')] [string]$HomeDirectory, # Log Directory [Parameter( Mandatory = $false, HelpMessage = 'Log Directory. Example: C:\inetpub\wwwroot')] [string]$LogDirectory, # Custom Config Path [Parameter( Mandatory = $false, HelpMessage = 'Custom Config Path. Example: C:\inetpub\DefaultConfig.ps1')] [string]$CustomConfig, # Custom Child Config Path [Parameter( Mandatory = $false, HelpMessage = 'Custom Child Config Path. Example: C:\inetpub\childconfig.ps1')] [string]$CustomChildConfig, # Custom Job Path [Parameter( Mandatory = $false, HelpMessage = 'Custom Job Path. Example: C:\inetpub\jobs.ps1')] [string]$CustomJob, # Custom Job Schedule [Parameter( Mandatory = $false, HelpMessage = 'Custom Job Schedule. Example: 1, 5, 10, 20, 30, 60')] [ValidateSet("1","5","10","20","30","60")] [string]$CustomJobSchedule = "5", # Background Job ID [Parameter( Mandatory = $false, HelpMessage = 'Background Job ID. Example: 52341')] [string]$JobID, # Background Job Username [Parameter( Mandatory = $false, HelpMessage = 'Background Job Username. Example: CONTOSO\Administrator')] [string]$JobUsername, # Background Job User Password [Parameter( Mandatory = $false, HelpMessage = 'Background Job User Password. Example: P@ssw0rd1')] [string]$JobPassword, # Background Job Credentials [Parameter( Mandatory = $false, HelpMessage = 'Run Background Job as Different User')] [switch]$JobCredentials = $false, # Enable SSL [Parameter( Mandatory = $false, HelpMessage = 'Enable SSL')] [switch]$SSL = $false, # Debug Mode [Parameter( Mandatory = $false, HelpMessage = 'Debug Mode')] [switch]$DebugMode = $false, # Background Job [Parameter( Mandatory = $false, HelpMessage = 'Run As Background Job')] [switch]$asJob = $false ) # Enable Debug Mode if ($DebugMode) { $DebugPreference = "Continue" } else { $ErrorActionPreference = "silentlycontinue" } # Get PoSH Server Path $PoSHServerPath = $PSScriptRoot # Get PoSH Server Module Path $PoSHModulePath = $PoSHServerPath # Test PoSH Server Module Path $PoSHModulePathTest = Test-Path $PoSHModulePath if (!$PoSHModulePathTest) { $ModulePaths = ($env:PSModulePath).Split(";") # Test Module Paths Foreach ($ModulePath in $ModulePaths) { $ModulePath = "$ModulePath\PoSHServer" $ModulePath = $ModulePath.Replace("\\","\") $PoSHModulePathTest = Test-Path $ModulePath if ($PoSHModulePathTest) { $PoSHModulePath = $ModulePath } } } if (!$PoSHModulePathTest) { Write-Warning "Could not detect PoSH Server Module Path." Write-Warning "Aborting.." $ResultCode = "-1" $ResultMessage = "Could not detect PoSH Server Module Path." } # Background Job Control if ($asJob -and $ResultCode -ne "-1") { if ($JobCredentials) { Write-Host " " Write-Host "Plase specify user credentials for PoSH Server background job." Write-Host " " $JobUsername = Read-Host -Prompt "Username" $JobSecurePassword = Read-Host -Prompt "Password" -AsSecureString $JobSecureCredentials = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $JobUsername,$JobSecurePassword $JobPassword = $JobSecureCredentials.GetNetworkCredential().Password } } # Background Job ID if ($JobID -and $ResultCode -ne "-1") { $JobIDPath = "$PoSHServerPath\jobs\job-$JobID.txt" $TestJobID = Test-Path $JobIDPath if ($JobIDPath) { $JobIDContent = Get-Content $JobIDPath $Hostname = $JobIDContent.Split(";")[0] $Port = $JobIDContent.Split(";")[1] $SSLIP = $JobIDContent.Split(";")[2] $SSLPort = $JobIDContent.Split(";")[3] $SSLName = $JobIDContent.Split(";")[4] $HomeDirectory = $JobIDContent.Split(";")[5] $LogDirectory = $JobIDContent.Split(";")[6] $CustomConfig = $JobIDContent.Split(";")[7] $CustomChildConfig = $JobIDContent.Split(";")[8] $CustomJob = $JobIDContent.Split(";")[9] } else { Write-Warning "Job ID is not exist." Write-Warning "Aborting.." $ResultCode = "-1" $ResultMessage = "Job ID is not exist." } } if ($ResultCode -ne "-1") { # Get Home and Log Directories if (!$HomeDirectory) { $HomeDirectory = "$PoSHServerPath\webroot\http" } if (!$LogDirectory) { $LogDirectory = "$PoSHServerPath\webroot\logs" } # Verify Admin Rights $Privileges = Confirm-PoSHAdminPrivileges if ($Privileges -ne "Validated") { Write-Host " " Write-Host "Please execute PoSH Server with administrative privileges." Write-Host "Aborting.." Write-Host " " $ShouldProcess = $false } # Verify Non SSL IP Address if ($Hostname) { $IPAddresses = @($Hostname.Split(",")) foreach ($IPAddress in $IPAddresses) { if ($IPAddress -ne "127.0.0.1" -and $IPAddress -ne "::1") { if ($IPAddress -as [ipaddress]) { $IPValidation = Confirm-PoSHServerIP -IP $IPAddress if ($IPValidation -ne "Validated") { Write-Warning "$IPAddress is not exist on your current network configuration." Write-Warning "Aborting.." $ShouldProcess = $false } } } } } # Verify SSL IP Address if ($SSLIP) { if ($ShouldProcess -ne $false) { $SSLIPAddresses = @($SSLIP.Split(",")) foreach ($SSLIPAddress in $SSLIPAddresses) { if ($SSLIPAddress -ne "127.0.0.1" -and $SSLIPAddress -ne "::1") { if ($SSLIPAddress -as [ipaddress]) { $IPValidation = Confirm-PoSHServerIP -IP $SSLIPAddress if ($IPValidation -ne "Validated") { Write-Warning "$SSLIPAddress is not exist on your current network configuration." Write-Warning "Aborting.." $ShouldProcess = $false } } } } } } # Break Script If Something's Wrong if ($ShouldProcess -eq $false) { $ResultCode = "-1" $ResultMessage = "Please check module output." } } if ($ResultCode -ne "-1") { # Enable Background Job if ($asJob) { if (!$Hostname) { $Hostname = "+" $TaskHostname = "localhost" } else { $TaskHostname = $Hostname.Split(",")[0] } if (!$Port) { $Port = "8080" $TaskPort = "8080" } else { $TaskPort = $Port.Split(",")[0] } if ($SSL) { if (!$SSLIP) { $SSLIP = "127.0.0.1" if (!$SSLPort) { $SSLPort = "8443" } } } $CheckTask = schtasks.exe | where {$_ -like "PoSHServer-$TaskHostname-$TaskPort*"} if ($CheckTask) { Write-Warning "This job is already exist. You should run it from Scheduled Jobs." Write-Warning "Aborting.." $ResultCode = "-1" $ResultMessage = "This job is already exist. You should run it from Scheduled Jobs." } else { # Prepare Job Information $TaskID = Get-Random -Maximum 10000 $TaskName = "PoSHServer-$TaskHostname-$TaskPort-$TaskID" $CreateJobIDPath = $PoSHServerPath + "\jobs\job-" + $TaskID + ".txt" $CreateJobIDValue = $Hostname + ";" + $Port + ";" + $SSLIP + ";" + $SSLPort + ";" + $SSLName + ";" + $HomeDirectory + ";" + $LogDirectory + ";" + $CustomConfig + ";" + $CustomChildConfig + ";" + $CustomJob $CreateJobID = Add-Content -Path $CreateJobIDPath -Value $CreateJobIDValue # Create Scheduled Jobs $CreateTask = schtasks /create /tn "$TaskName" /xml "$PoSHServerPath\jobs\template.xml" /ru SYSTEM $ChangeTaskProcess = $true while ($ChangeTaskProcess) { if ($SSL) { $ChangeTask = schtasks /change /tn "$TaskName" /tr "Powershell -Command &{Import-Module PoSHServer; Start-PoSHServer -SSL -JobID $TaskID}" /rl highest } else { $ChangeTask = schtasks /change /tn "$TaskName" /tr "Powershell -Command &{Import-Module PoSHServer; Start-PoSHServer -JobID $TaskID}" /rl highest } if ($ChangeTask) { $ChangeTaskProcess = $false } } if ($JobUsername -and $JobPassword) { $ChangeTaskProcess = $true while ($ChangeTaskProcess) { $ChangeTask = schtasks /tn "$TaskName" /Change /RU "$JobUsername" /RP "$JobPassword" if ($ChangeTask) { $ChangeTaskProcess = $false } } } # Start Background Job $RunTask = schtasks /run /tn "$TaskName" # PoSH Server Welcome Banner Get-PoSHWelcomeBanner -Hostname $Hostname -Port $Port -SSL $SSL -SSLIP $SSLIP -SSLPort $SSLPort -DebugMode $DebugMode } } else { # PoSH Server Scheduled Background Jobs $PoSHJobArgs = @($Hostname,$Port,$HomeDirectory,$LogDirectory,$PoSHModulePath,$asJob) $PoSHJob = Start-Job -scriptblock { param ($Hostname, $Port, $HomeDirectory, $LogDirectory, $PoSHModulePath, $asJob) # PoSH Server Custom Configuration $PoSHCustomConfigPath = $HomeDirectory + "\DefaultConfig.ps1" # Test Config Path $TestPoSHCustomConfigPath = Test-Path $PoSHCustomConfigPath if (!$TestPoSHCustomConfigPath) { # Import Config . $PoSHModulePath\modules\DefaultConfig.ps1 } else { # Import Config . $HomeDirectory\DefaultConfig.ps1 } while ($true) { Start-Sleep -s 60 # Get Job Time $JobTime = Get-Date -format HHmm if ($LogSchedule -eq "Hourly") { # PoSH Server Log Hashing (at *:30 hourly) if ($JobTime -eq "*30") { New-PoSHLogHash -LogSchedule $LogSchedule -LogDirectory $LogDirectory } } else { # PoSH Server Log Hashing (at 02:30 daily) if ($JobTime -eq "0230") { New-PoSHLogHash -LogSchedule $LogSchedule -LogDirectory $LogDirectory } } } } -ArgumentList $PoSHJobArgs # PoSH Server Custom Background Jobs $PoSHCustomJobArgs = @($Hostname,$Port,$HomeDirectory,$LogDirectory,$PoSHModulePath,$CustomJob,$CustomJobSchedule,$asJob) $PoSHCustomJob = Start-Job -scriptblock { param ($Hostname, $Port, $HomeDirectory, $LogDirectory, $PoSHModulePath, $CustomJob, $CustomJobSchedule, $asJob) # PoSH Server Custom Configuration $PoSHCustomConfigPath = $HomeDirectory + "\DefaultConfig.ps1" # Test Config Path $TestPoSHCustomConfigPath = Test-Path $PoSHCustomConfigPath if (!$TestPoSHCustomConfigPath) { # Import Config . $PoSHModulePath\modules\DefaultConfig.ps1 } else { # Import Config . $HomeDirectory\DefaultConfig.ps1 } while ($true) { Start-Sleep -s 60 # Get Job Time $JobTime = Get-Date -format HHmm if ($CustomJobSchedule -eq "1") { # PoSH Server Custom Jobs (at every 1 minute) if ($CustomJob) { . $CustomJob } } elseif ($CustomJobSchedule -eq "5") { # PoSH Server Custom Jobs (at every 5 minutes) if ($JobTime -like "*5" -or $JobTime -like "*0") { if ($CustomJob) { . $CustomJob } } } elseif ($CustomJobSchedule -eq "10") { # PoSH Server Custom Jobs (at every 10 minutes) if ($JobTime -like "*00" -or $JobTime -like "*10" -or $JobTime -like "*20" -or $JobTime -like "*30" -or $JobTime -like "*40" -or $JobTime -like "*50") { if ($CustomJob) { . $CustomJob } } } elseif ($CustomJobSchedule -eq "20") { # PoSH Server Custom Jobs (at every 20 minutes) if ($JobTime -like "*00" -or $JobTime -like "*20" -or $JobTime -like "*40") { if ($CustomJob) { . $CustomJob } } } elseif ($CustomJobSchedule -eq "30") { # PoSH Server Custom Jobs (at every 30 minutes) if ($JobTime -like "*00" -or $JobTime -like "*30") { if ($CustomJob) { . $CustomJob } } } elseif ($CustomJobSchedule -eq "60") { # PoSH Server Custom Jobs (at every hour) if ($JobTime -like "*00") { if ($CustomJob) { . $CustomJob } } } else { # PoSH Server Custom Jobs (at every 5 minutes) if ($JobTime -like "*5" -or $JobTime -like "*0") { if ($CustomJob) { . $CustomJob } } } } } -ArgumentList $PoSHCustomJobArgs # PoSH Server Custom Config if ($CustomConfig) { . $CustomConfig } # Create an HTTPListener try { $Listener = New-Object Net.HttpListener } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } # Add Prefix Urls try { if (!$Hostname) { $Hostname = "+" if (!$Port) { $Port = "8080" } $Prefix = "http://" + $Hostname + ":" + $Port + "/" $Listener.Prefixes.Add($Prefix) } else { $Hostnames = @($Hostname.Split(",")) if (!$Port) { $Port = "8080" } foreach ($Hostname in $Hostnames) { $Prefix = "http://" + $Hostname + ":" + $Port + "/" $Listener.Prefixes.Add($Prefix) } } if ($SSL) { if (!$SSLIP) { $SSLIP = "127.0.0.1" if (!$SSLPort) { $SSLPort = "8443" } $Prefix = "https://" + $SSLIP + ":" + $SSLPort + "/" $Listener.Prefixes.Add($Prefix) } else { $SSLIPAddresses = @($SSLIP.Split(",")) if (!$SSLPort) { $SSLPort = "8443" } foreach ($SSLIPAddress in $SSLIPAddresses) { $Prefix = "https://" + $SSLIPAddress + ":" + $SSLPort + "/" $Listener.Prefixes.Add($Prefix) } } } } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } # Start Listener try { $Listener.Start() } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } # Configure SSL try { if ($SSL) { if ($SSLName) { $PoSHCert = Get-ChildItem -Recurse Cert: | Where-Object { $_.FriendlyName -eq $SSLName } if (!$PoSHCert) { $PoSHCert = Get-ChildItem -Recurse Cert: | Where-Object { $_.FriendlyName -eq "PoSHServer SSL Certificate" } } } else { $PoSHCert = Get-ChildItem -Recurse Cert: | Where-Object { $_.FriendlyName -eq "PoSHServer SSL Certificate" } } if (!$PoSHCert) { if ($DebugMode) { Add-Content -Value "Sorry, I couldn't find your SSL certificate." -Path "$LogDirectory\debug.txt" Add-Content -Value "Creating Self-Signed SSL certificate.." -Path "$LogDirectory\debug.txt" } Request-PoSHCertificate $PoSHCert = Get-ChildItem -Recurse Cert: | Where-Object { $_.FriendlyName -eq "PoSHServer SSL Certificate" } } # Register SSL Certificate $CertThumbprint = $PoSHCert[0].Thumbprint Register-PoSHCertificate -SSLIP $SSLIP -SSLPort $SSLPort -Thumbprint $CertThumbprint -DebugMode $DebugMode } } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } # PoSH Server Welcome Banner try { Get-PoSHWelcomeBanner -Hostname $Hostname -Port $Port -SSL $SSL -SSLIP $SSLIP -SSLPort $SSLPort -DebugMode $DebugMode } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } # PoSH Server Async Process Script $ScriptBlock = ` { Param($Listener, $Hostname, $Hostnames, $HomeDirectory, $LogDirectory, $PoSHModulePath, $CustomChildConfig, $DebugMode) # Enable Debug Mode if ($DebugMode) { $DebugPreference = "Continue" } else { $ErrorActionPreference = "silentlycontinue" } # PoSH Server Custom Child Config if ($CustomChildConfig) { . $CustomChildConfig } # Create loop $ShouldProcess = $true # Get Server Requests while ($ShouldProcess) { # PoSH Server Custom Configuration $PoSHCustomConfigPath = $HomeDirectory + "\DefaultConfig.ps1" # Test Config Path $TestPoSHCustomConfigPath = Test-Path $PoSHCustomConfigPath if (!$TestPoSHCustomConfigPath) { # Import Config . $PoSHModulePath\modules\DefaultConfig.ps1 } else { # Import Config . $HomeDirectory\DefaultConfig.ps1 } # Reset Authentication $Listener.AuthenticationSchemes = "Anonymous"; # Set Authentication if ($BasicAuthentication -eq "On") { $Listener.AuthenticationSchemes = "Basic"; } if ($NTLMAuthentication -eq "On") { $Listener.AuthenticationSchemes = "NTLM"; } if ($WindowsAuthentication -eq "On") { $Listener.AuthenticationSchemes = "IntegratedWindowsAuthentication"; } # Open Connection $Context = $Listener.GetContext() # Setup Basic Authentication (If Required From Config File) if ($BasicAuthentication -eq "On") { $Identity = $Context.User.Identity; $PoSHUserName = $Identity.Name $PoSHUserPassword = $Identity.Password } # Setup Windows Authentication (If Required From Config File) if ($WindowsAuthentication -eq "On") { $Identity = $Context.User.Identity; $PoSHUserName = $Identity.Name } # Set Home Directory [IO.Directory]::SetCurrentDirectory("$HomeDirectory") $File = $Context.Request.Url.LocalPath $Response = $Context.Response $Response.Headers.Add("Accept-Encoding","gzip"); $Response.Headers.Add("Server","PoSH Server"); $Response.Headers.Add("X-Powered-By","Microsoft PowerShell"); # Set Request Parameters $Request = $Context.Request $InputStream = $Request.InputStream $ContentEncoding = $Request.ContentEncoding # Setup IP Restrictions (If Required By Config File) $ClientIPAddr = $Request.RemoteEndPoint.Address if ($IPRestriction -eq "On") { if (!($IPWhiteList -match $ClientIPAddr)) { Write-Warning "$ClientIPAddr has no permission, dropping.." $IPSessionDrop = "1"; } else { $IPSessionDrop = "0"; } } else { $IPSessionDrop = "0"; } # Get Query String $PoSHQuery = Get-PoSHQueryString -Request $Request # Get Post Stream $PoSHPost = Get-PoSHPostStream -InputStream $InputStream -ContentEncoding $ContentEncoding # Cookie Information $PoSHCookies = $Request.Cookies["PoSHSessionID"]; if (!$PoSHCookies) { $PoSHCookie = New-Object Net.Cookie $PoSHCookie.Name = "PoSHSessionID" $PoSHCookie.Value = New-PoSHTimeStamp $Response.AppendCookie($PoSHCookie) } # Get Default Document if ($File -notlike "*.*" -and $File -like "*/") { $FolderPath = [System.IO.Directory]::GetCurrentDirectory() + $File $RequstURL = [string]$Request.Url $SubfolderName = $File $File = $File + $DefaultDocument } elseif ($File -notlike "*.*" -and $File -notlike "*/") { $FolderPath = [System.IO.Directory]::GetCurrentDirectory() + $File + "/" $RequstURL = [string]$Request.Url + "/" $SubfolderName = $File + "/" $File = $File + "/" + $DefaultDocument } else { $FolderPath = $Null; } # PoSH API Support if ($File -like "*.psxml") { $File = $File.Replace(".psxml",".ps1") # Full File Path $File = [System.IO.Directory]::GetCurrentDirectory() + $File # Get Mime Type $MimeType = "text/psxml" } else { # Full File Path $File = [System.IO.Directory]::GetCurrentDirectory() + $File # Get Mime Type $FileExtension = (Get-ChildItem $File -EA SilentlyContinue).Extension $MimeType = Get-MimeType $FileExtension } #Verify Mimetype Is Supported if ($ContentFiltering -eq "On") { if ($ContentFilterBlackList -match $MimeType) { Write-Debug "$MimeType is not allowed, dropping.." $ContentSessionDrop = "1"; } else { $ContentSessionDrop = "0"; } } else { $ContentSessionDrop = "0"; } # Stream Content if ([System.IO.File]::Exists($File) -and $ContentSessionDrop -eq "0" -and $IPSessionDrop -eq "0") { if ($MimeType -eq "text/ps1") { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $File)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } elseif ($MimeType -eq "text/psxml") { try { $Response.ContentType = "text/xml" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $File)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } elseif ($MimeType -eq "text/php") { try { if ($PHPCgiPath) { $TestPHPCgiPath = Test-Path -Path $PHPCgiPath } else { $TestPHPCgiPath = $false } if ($TestPHPCgiPath) { if ($File -like "C:\Windows\*") { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\403.ps1)") } else { $Response.ContentType = "text/html" $PHPContentOutput = Get-PoSHPHPContent -PHPCgiPath "$PHPCgiPath" -File "$File" -PoSHPHPGET $PoSHQuery.PoSHQueryString -PoSHPHPPOST $PoSHPost.PoSHPostStream $PHPContentOutput = Set-PHPEncoding -PHPOutput $PHPContentOutput $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$PHPContentOutput") } } else { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\500.ps1)") } } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } else { try { $Response.ContentType = "$MimeType" $FileContent = [System.IO.File]::ReadAllBytes($File) $Response.ContentLength64 = $FileContent.Length $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response.OutputStream.Write($FileContent, 0, $FileContent.Length) } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } else { # Content Filtering and IP Restriction Control if ($ContentSessionDrop -eq "0" -and $IPSessionDrop -eq "0") { if ($FolderPath) { $TestFolderPath = Test-Path -Path $FolderPath } else { $TestFolderPath = $false } } else { $TestFolderPath = $false } if ($DirectoryBrowsing -eq "On" -and $TestFolderPath) { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) if ($Hostname -eq "+") { $HeaderName = "localhost" } else { $HeaderName = $Hostnames[0] } $DirectoryContent = (Get-DirectoryContent -Path "$FolderPath" -HeaderName $HeaderName -RequestURL $RequestURL -SubfolderName $SubfolderName) $Response.WriteLine("$DirectoryContent") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } else { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\404.ps1)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } # Logging Module . $PoSHModulePath\modules\Logging.ps1 # Close Connection try { $Response.Close() } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } if ($DebugMode) { # Invoke PoSH Server Multithread Process - Thread 1 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig -DebugMode | Out-Null # Invoke PoSH Server Multithread Process - Thread 2 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig -DebugMode | Out-Null # Invoke PoSH Server Multithread Process - Thread 3 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig -DebugMode | Out-Null } else { # Invoke PoSH Server Multithread Process - Thread 1 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig | Out-Null # Invoke PoSH Server Multithread Process - Thread 2 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig | Out-Null # Invoke PoSH Server Multithread Process - Thread 3 Invoke-AsyncHTTPRequest -ScriptBlock $ScriptBlock -Listener $Listener -Hostname $Hostname -Hostnames $Hostnames -HomeDirectory $HomeDirectory -LogDirectory $LogDirectory -PoSHModulePath $PoSHModulePath -CustomChildConfig $CustomChildConfig | Out-Null } # Create loop $ShouldProcess = $true # Get Server Requests while ($ShouldProcess) { # PoSH Server Custom Configuration $PoSHCustomConfigPath = $HomeDirectory + "\DefaultConfig.ps1" # Test Config Path $TestPoSHCustomConfigPath = Test-Path $PoSHCustomConfigPath if (!$TestPoSHCustomConfigPath) { # Import Config . $PoSHModulePath\modules\DefaultConfig.ps1 } else { # Import Config . $HomeDirectory\DefaultConfig.ps1 } # Reset Authentication $Listener.AuthenticationSchemes = "Anonymous"; # Set Authentication if ($BasicAuthentication -eq "On") { $Listener.AuthenticationSchemes = "Basic"; } if ($NTLMAuthentication -eq "On") { $Listener.AuthenticationSchemes = "NTLM"; } if ($WindowsAuthentication -eq "On") { $Listener.AuthenticationSchemes = "IntegratedWindowsAuthentication"; } # Open Connection $Context = $Listener.GetContext() # Setup Basic Authentication (If Required From Config File) if ($BasicAuthentication -eq "On") { $Identity = $Context.User.Identity; $PoSHUserName = $Identity.Name $PoSHUserPassword = $Identity.Password } # Setup Windows Authentication (If Required From Config File) if ($WindowsAuthentication -eq "On") { $Identity = $Context.User.Identity; $PoSHUserName = $Identity.Name } # Set Home Directory [IO.Directory]::SetCurrentDirectory("$HomeDirectory") $File = $Context.Request.Url.LocalPath $Response = $Context.Response $Response.Headers.Add("Accept-Encoding","gzip"); $Response.Headers.Add("Server","PoSH Server"); $Response.Headers.Add("X-Powered-By","Microsoft PowerShell"); # Set Request Parameters $Request = $Context.Request $InputStream = $Request.InputStream $ContentEncoding = $Request.ContentEncoding # Setup IP Restrictions (If Required By Config File) $ClientIPAddr = $Request.RemoteEndPoint.Address if ($IPRestriction -eq "On") { if (!($IPWhiteList -match $ClientIPAddr)) { Write-Warning "$ClientIPAddr has no permission, dropping.." $IPSessionDrop = "1"; } else { $IPSessionDrop = "0"; } } else { $IPSessionDrop = "0"; } # Get Query String $PoSHQuery = Get-PoSHQueryString -Request $Request # Get Post Stream $PoSHPost = Get-PoSHPostStream -InputStream $InputStream -ContentEncoding $ContentEncoding # Cookie Information $PoSHCookies = $Request.Cookies["PoSHSessionID"]; if (!$PoSHCookies) { $PoSHCookie = New-Object Net.Cookie $PoSHCookie.Name = "PoSHSessionID" $PoSHCookie.Value = New-PoSHTimeStamp $Response.AppendCookie($PoSHCookie) } # Get Default Document if ($File -notlike "*.*" -and $File -like "*/") { $FolderPath = [System.IO.Directory]::GetCurrentDirectory() + $File $RequstURL = [string]$Request.Url $SubfolderName = $File $File = $File + $DefaultDocument } elseif ($File -notlike "*.*" -and $File -notlike "*/") { $FolderPath = [System.IO.Directory]::GetCurrentDirectory() + $File + "/" $RequstURL = [string]$Request.Url + "/" $SubfolderName = $File + "/" $File = $File + "/" + $DefaultDocument } else { $FolderPath = $Null; } # PoSH API Support if ($File -like "*.psxml") { $File = $File.Replace(".psxml",".ps1") # Full File Path $File = [System.IO.Directory]::GetCurrentDirectory() + $File # Get Mime Type $MimeType = "text/psxml" } else { # Full File Path $File = [System.IO.Directory]::GetCurrentDirectory() + $File # Get Mime Type $FileExtension = (Get-ChildItem $File -EA SilentlyContinue).Extension $MimeType = Get-MimeType $FileExtension } #Verify Mimetype Is Supported if ($ContentFiltering -eq "On") { if ($ContentFilterBlackList -match $MimeType) { Write-Debug "$MimeType is not allowed, dropping.." $ContentSessionDrop = "1"; } else { $ContentSessionDrop = "0"; } } else { $ContentSessionDrop = "0"; } # Stream Content if ([System.IO.File]::Exists($File) -and $ContentSessionDrop -eq "0" -and $IPSessionDrop -eq "0") { if ($MimeType -eq "text/ps1") { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $File)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } elseif ($MimeType -eq "text/psxml") { try { $Response.ContentType = "text/xml" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $File)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } elseif ($MimeType -eq "text/php") { try { if ($PHPCgiPath) { $TestPHPCgiPath = Test-Path -Path $PHPCgiPath } else { $TestPHPCgiPath = $false } if ($TestPHPCgiPath) { if ($File -like "C:\Windows\*") { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\403.ps1)") } else { $Response.ContentType = "text/html" $PHPContentOutput = Get-PoSHPHPContent -PHPCgiPath "$PHPCgiPath" -File "$File" -PoSHPHPGET $PoSHQuery.PoSHQueryString -PoSHPHPPOST $PoSHPost.PoSHPostStream $PHPContentOutput = Set-PHPEncoding -PHPOutput $PHPContentOutput $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$PHPContentOutput") } } else { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\500.ps1)") } } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } else { try { $Response.ContentType = "$MimeType" $FileContent = [System.IO.File]::ReadAllBytes($File) $Response.ContentLength64 = $FileContent.Length $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response.OutputStream.Write($FileContent, 0, $FileContent.Length) } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } else { # Content Filtering and IP Restriction Control if ($ContentSessionDrop -eq "0" -and $IPSessionDrop -eq "0") { if ($FolderPath) { $TestFolderPath = Test-Path -Path $FolderPath } else { $TestFolderPath = $false } } else { $TestFolderPath = $false } if ($DirectoryBrowsing -eq "On" -and $TestFolderPath) { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::OK $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) if ($Hostname -eq "+") { $HeaderName = "localhost" } else { $HeaderName = $Hostnames[0] } $DirectoryContent = (Get-DirectoryContent -Path "$FolderPath" -HeaderName $HeaderName -RequestURL $RequestURL -SubfolderName $SubfolderName) $Response.WriteLine("$DirectoryContent") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } else { try { $Response.ContentType = "text/html" $Response.StatusCode = [System.Net.HttpStatusCode]::NotFound $LogResponseStatus = $Response.StatusCode $Response = New-Object IO.StreamWriter($Response.OutputStream,[Text.Encoding]::UTF8) $Response.WriteLine("$(. $PoSHModulePath\webroot\http\404.ps1)") } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } } # Logging Module . $PoSHModulePath\modules\Logging.ps1 # Close Connection try { $Response.Close() } catch { Add-Content -Value $_ -Path "$LogDirectory\debug.txt" } } # Stop Listener $Listener.Stop() } } } |