private/Get-TCPWriter.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
Function Get-TCPWriter
{
    <#
        .SYNOPSIS
        Returns a TCPWriter object for a given TcpClient.
 
        .DESCRIPTION
        Creates a TcpWriter, given the TcpClient (and TcpStream), and returns it.
 
        .EXAMPLE
        Get-TCPWriter -TcpClient $Client
        Returns a TCPWriter connected to the stream associated with the TCPClient.
 
        .OUTPUTS
        System.IO.StreamWriter
    #>


    [CmdletBinding(DefaultParameterSetName = 'TLSDisabled')]
    [OutputType([System.IO.StreamWriter])]
    param
    (
        # TCP Client that is connected to an endpoint
        [Parameter(Mandatory   = $true,
                   HelpMessage = 'TCP Client that is connected to an endpoint')]
        [ValidateNotNullOrEmpty()]
        [Net.Sockets.TcpClient]
        $TcpClient,

        # Enables support for TLS
        [Parameter(Mandatory        = $true,
                   ParameterSetName = 'UseTLS')]
        [switch]
        $UseTLS,

        # Server Hostname to validate against the certificate presented during TLS validation
        [Parameter(Mandatory        = $true,
                   ParameterSetName = 'UseTLS')]
        [string]
        $ServerHostname,

        # SSL Protocols accepted
        [Parameter(Mandatory        = $false,
                   ParameterSetName = 'UseTLS')]
        [System.Security.Authentication.SslProtocols]
        $SslProtocols = [System.Security.Authentication.SslProtocols]::Tls12,

        # Do not validate TLS Certificate
        [Parameter(Mandatory        = $false,
                   ParameterSetName = 'UseTLS')]
        [switch]
        $DoNotValidateTLSCertificate
    )

    Try
    {
        if ($UseTLS)
        {
            Write-Debug -Message 'Using TCP connection with TLS/SSL'
            if ($DoNotValidateTLSCertificate)
            {
                # See https://docs.microsoft.com/en-us/dotnet/api/system.net.security.sslstream.-ctor?view=netframework-4.7.2 and
                # https://stackoverflow.com/questions/19252963/powershell-ssl-socket-client
                Write-Warning -Message 'Ignoring SSL/TLS certificate validation issues'
                $TCPStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList ($TCPClient.GetStream(), $false, {$True})
            }
            else
            {
                $TCPStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList ($TCPClient.GetStream(), $false)
            }

            $TCPStream.AuthenticateAsClient($ServerHostname, $null, $SslProtocols, $false)
        }
        else
        {
            $TcpStream = $TcpClient.GetStream()
        }

        $TcpWriter = New-Object -TypeName System.IO.StreamWriter -ArgumentList $TcpStream

        # We want to set autoflush to true so that we send whatever is in the stream/writer when a newline is entered
        $TcpWriter.AutoFlush = $true
    }
    Catch
    {
        Throw $_
    }

    $TcpWriter
}