TunableSSLValidator.psm1
if(-not ("Huddled.Net.TunableValidator" -as [Type])) { Add-Type -Path "${PSScriptRoot}\TunableValidator.cs" } # You need to set the validator so it can do anything... [Huddled.Net.TunableValidator]::SetValidator() function Request-WebCertificate { #.Synopsis # Make an SSL web request and return the SSL certificate [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] [CmdletBinding()] param( # The URL to fetch the SSL certificate from [Uri][String]$url = "https://www.csh.rit.edu" ) process { if(!$Url.Scheme) { $url = "https://" + $Url } if($url.Scheme -ne "https") { Write-Warning "Url is not HTTPS" $url = "https://" + $url.Host + ":" + $url.Port + $url.PathAndQuery } $web = [Net.WebRequest]::Create($url) -as [Net.HttpWebRequest] $SSLCallback = { param($sender, $certificate, $chain, $sslPolicyErrors) $script:RequestedWebCertificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $certificate return $true } if($web | Get-Member ServerCertificateValidationCallback) { $web.ServerCertificateValidationCallback = $SSLCallback $null = $web.GetResponse() } else { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $SSLCallback $null = $web.GetResponse() [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null } return $RequestedWebCertificate } } function Add-WindowsTrustedCertificate { #.Synopsis # Add a certificate to the Windows certificate store [CmdletBinding(DefaultParameterSetName = 'Certificate')] param( [Parameter(ParameterSetName = "Certificate", Mandatory = $True, Position=0, ValueFromPipeline = $True)] [System.Security.Cryptography.X509Certificates.X509Certificate]$Certificate, [Parameter(ParameterSetName = "Path", Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Alias("PSPath")] [String]$FilePath, [Parameter(ParameterSetName = "Path")] [SecureString]$Password = $((Get-Credential $FilePath).Password), [ValidateSet("CurrentUser","LocalMachine")] [String]$Root = "CurrentUser", [String]$certStore = "My" ) process { if($FilePath) { if(-not (Test-Path $FilePath)) { throw "Certificate File Not Found at '$FilePath'" } $Certificate = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 if ($Password -eq $null) { $Certificate.import( (Convert-Path $FilePath) ) } else { $Certificate.import( (Convert-Path $FilePath), $Password, "Exportable,PersistKeySet" ) } } $store = new-object System.Security.Cryptography.X509Certificates.X509Store($certStore, $Root) $store.open("MaxAllowed") $store.add($Certificate) $store.close() } } function Add-SessionTrustedCertificate { #.Synopsis # Map a certificate to a URL for this PowerShell session (does not permanently import the certificate) [CmdletBinding(DefaultParameterSetName = 'Certificate')] param( [Parameter(ParameterSetName = "Certificate", Mandatory = $True, Position=0, ValueFromPipeline = $True)] [System.Security.Cryptography.X509Certificates.X509Certificate]$Certificate, [Parameter(ParameterSetName = "Path", Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Alias("PSPath")] [String]$FilePath, [Parameter(ParameterSetName = "CertHash", Mandatory = $True)] [String]$Hash, [Parameter(ParameterSetName = "LastFailedCert", Mandatory = $True)] [Switch]$LastFailed, [Parameter(ParameterSetName = "NextFailingCert", Mandatory = $True)] [Switch]$NextFailingCert, [Parameter(ParameterSetName = "Certificate", Mandatory = $true, Position = 1)] [Parameter(ParameterSetName = "Path", Mandatory = $true, Position = 1)] [Parameter(ParameterSetName = "CertHash", Mandatory = $true, Position = 1)] [Uri]$Domain ) process { if($LastFailed) { [Huddled.Net.TunableValidator]::ApproveLastRequest() } elseif($NextFailingCert) { [Huddled.Net.TunableValidator]::ApproveNextRequest($True) } else { if($FilePath) { if(-not (Test-Path $FilePath)) { throw "Certificate File Not Found at '$FilePath'" } $Certificate = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 if ($Password -eq $null) { $Certificate.import( (Convert-Path $FilePath) ) } else { $Certificate.import( (Convert-Path $FilePath), $Password, "Exportable,PersistKeySet" ) } } if($Certificate) { $Hash = $Certificate.GetCertHashString() } $dnsName = $(if($Domain.Authority) { $Domain.Authority }elseif($Domain.Host){$Domain.Host}else{$Domain.originalstring}) [Huddled.Net.TunableValidator]::TrustedCerts[$Hash] = $dnsname } } } function Get-SessionTrustedCertificate { foreach($key in @([Huddled.Net.TunableValidator]::TrustedCerts.Keys)) { New-Object PSObject -Property @{ "CertHash" = $key "Domain" = [Huddled.Net.TunableValidator]::TrustedCerts[$key] } } } function Remove-SessionTrustedCertificate { param( [Parameter(ParameterSetName = "CertHash", Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [Alias("CertHash")] [String]$Hash ) process { Write-Verbose "Removing $Hash" if(![Huddled.Net.TunableValidator]::TrustedCerts.Remove($Hash)) { Write-Error "Couldn't find $Hash in TrustedCerts" } } } function Disable-ShowConsoleStandardOutput { #.Synopsis # Disables methods from writing to the standard output stream [Huddled.Net.TunableValidator]::ShowConsoleStandardOutput = $False } function Enable-ShowConsoleStandardOutput { #.Synopsis # Enables methods to write to the standard output stream [Huddled.Net.TunableValidator]::ShowConsoleStandardOutput = $True } function Get-ShowConsoleStandardOutput { #.Synopsis # Retrieves the setting for whether methods to write to the standard output stream [Huddled.Net.TunableValidator]::ShowConsoleStandardOutput } function Disable-SSLChainValidation { #.Synopsis # Disables validation of the SSL certificate chain, essentially allowing self-signed certificates [Huddled.Net.TunableValidator]::IgnoreChainErrors = $True } function Enable-SSLChainValidation { #.Synopsis # Enables normal validation of the SSL certificate chain [Huddled.Net.TunableValidator]::IgnoreChainErrors = $False } function Get-IgnoreChainErrors { #.Synopsis # Retrieves validation setting for the SSL certificate chain [Huddled.Net.TunableValidator]::IgnoreChainErrors } function Invoke-WebRequest { [CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkID=217035')] param( [switch] ${UseBasicParsing}, [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [uri] ${Uri}, [Microsoft.PowerShell.Commands.WebRequestSession] ${WebSession}, [Alias('SV')] [string] ${SessionVariable}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${Credential}, [switch] ${UseDefaultCredentials}, [ValidateNotNullOrEmpty()] [string] ${CertificateThumbprint}, [ValidateNotNull()] [System.Security.Cryptography.X509Certificates.X509Certificate] ${Certificate}, [string] ${UserAgent}, [switch] ${DisableKeepAlive}, [int] ${TimeoutSec}, [System.Collections.IDictionary] ${Headers}, [ValidateRange(0, 2147483647)] [int] ${MaximumRedirection}, [Microsoft.PowerShell.Commands.WebRequestMethod] ${Method}, [uri] ${Proxy}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${ProxyCredential}, [switch] ${ProxyUseDefaultCredentials}, [Parameter(ValueFromPipeline=$true)] [System.Object] ${Body}, [string] ${ContentType}, [ValidateSet('chunked','compress','deflate','gzip','identity')] [string] ${TransferEncoding}, [string] ${InFile}, [string] ${OutFile}, [switch] ${PassThru}, # Ignore SSL Errors for this request [switch] [Alias("Insecure")] ${SkipCertificateCheck} ) begin { if($SkipCertificateCheck) { [Huddled.Net.TunableValidator]::ApproveNextRequest() } $null = $PSBoundParameters.Remove("SkipCertificateCheck") try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Invoke-WebRequest', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() if ($PSBoundParameters.ContainsKey("SessionVariable")) { # because we're in module scope, the caller scope is two up $session = Get-Variable -Name $SessionVariable -ValueOnly Set-Variable -Name $SessionVariable -Value $session -Scope 2 } } catch { throw } } <# .ForwardHelpTargetName Microsoft.PowerShell.Utility\Invoke-WebRequest .ForwardHelpCategory Cmdlet #> } function Invoke-RestMethod { [CmdletBinding(HelpUri='http://go.microsoft.com/fwlink/?LinkID=217034')] param( [Microsoft.PowerShell.Commands.WebRequestMethod] ${Method}, [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [uri] ${Uri}, [Microsoft.PowerShell.Commands.WebRequestSession] ${WebSession}, [Alias('SV')] [string] ${SessionVariable}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${Credential}, [switch] ${UseDefaultCredentials}, [ValidateNotNullOrEmpty()] [string] ${CertificateThumbprint}, [ValidateNotNull()] [System.Security.Cryptography.X509Certificates.X509Certificate] ${Certificate}, [string] ${UserAgent}, [switch] ${DisableKeepAlive}, [int] ${TimeoutSec}, [System.Collections.IDictionary] ${Headers}, [ValidateRange(0, 2147483647)] [int] ${MaximumRedirection}, [uri] ${Proxy}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${ProxyCredential}, [switch] ${ProxyUseDefaultCredentials}, [Parameter(ValueFromPipeline=$true)] [System.Object] ${Body}, [string] ${ContentType}, [ValidateSet('chunked','compress','deflate','gzip','identity')] [string] ${TransferEncoding}, [string] ${InFile}, [string] ${OutFile}, [switch] ${PassThru}, # Ignore SSL Errors for this request [switch] [Alias("Insecure")] ${SkipCertificateCheck} ) begin { if($SkipCertificateCheck) { [Huddled.Net.TunableValidator]::ApproveNextRequest() } $null = $PSBoundParameters.Remove("SkipCertificateCheck") try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Invoke-RestMethod', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() if($PSBoundParameters.ContainsKey("SessionVariable")) { # because we're in module scope, the caller scope is two up $session = Get-Variable -Name $SessionVariable -ValueOnly Set-Variable -Name $SessionVariable -Value $session -Scope 2 } } catch { throw } } <# .ForwardHelpTargetName Microsoft.PowerShell.Utility\Invoke-RestMethod .ForwardHelpCategory Cmdlet #> } if(Get-Command Export-ODataEndpointProxy -ErrorAction SilentlyContinue) { function Export-ODataEndpointProxy { [CmdletBinding(DefaultParameterSetName='CDXML')] param( [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [string] ${Uri}, [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true)] [string] ${OutputPath}, [Parameter(Position=2, ValueFromPipelineByPropertyName=$true)] [string] ${MetadataUri}, [Parameter(Position=3, ValueFromPipelineByPropertyName=$true)] [pscredential] [System.Management.Automation.CredentialAttribute()] ${Credential}, [switch] [Alias("Insecure")] ${SkipCertificateCheck} ) begin { if($SkipCertificateCheck) { [Huddled.Net.TunableValidator]::ApproveNextRequest() } $null = $PSBoundParameters.Remove("SkipCertificateCheck") try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.ODataUtils\Export-ODataEndpointProxy', [System.Management.Automation.CommandTypes]::Function) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } <# .ForwardHelpTargetName Microsoft.PowerShell.ODataUtils\Export-ODataEndpointProxy .ForwardHelpCategory Function #> } } # Should add a module unload hook to remove the validation hook # [Net.ServicePointManager]::ServerCertificateValidationCallback = $null |