# Get-TCPCert # # Use Pipeline for list of Hostnames or IP-Addresses # # Pending: Check Revocation http://poshcode.org/1633 # Pending: Check Issuer http://poshcode.org/1633 # Pending: Check CN/SAN-Name # Pending: Parallelisierung # 20161115 inital Version 1.0 and 1.1 # 20181115 Added TLS 1.2 enforcement switch # 20190405 Anpassung bei SSLFail # 20210201 Handling of TLSHandshakeFail fixed, Stopwatch added, Details about DNS-Name and IP-Address [cmdletbinding()] param ( [Parameter(ValueFromPipeline=$True,Mandatory)] [string]$remotehost, [uint16]$port=443, [long]$tcptimeout= 1000, # wait up to 1Sec for TCP Connection [ValidateSet($null,"","Default","TLS","TLS11","TLS12","TLS13","SSL3")] [string]$tlsmode="Default" ) begin { set-psdebug -strict write-host "Get-TCPCert: Start" $stopwatch = [system.diagnostics.stopwatch]::new() } process { write-host "------------- Get-TCPCert:Processing $remotehost" $result = "" | Select-Object datetime,Computername,remotename,remoteip,Port,Status,CN,Subject,NotAfter,NotBefore,Issuer,Thumbprint,SerialNumber,SignatureAlgorithmFriendlyName,dnstimems,connecttimems,tlstimems,totaltimems $result.datetime = ((get-date).ToUniversalTime().tostring("u")) $result.Computername = $remotehost $result.Port = $port $result.Status = $null $stopwatch.Restart() if ($remotehost -as [ipaddress]) { write-host " Using given IP-Address. NoDNS" $dnsanswer = $remotehost $remoteip = $remotehost $result.dnstimems = "" } else { write-host " Resolving Hostname: $($remotehost)" $dnsanswer = (Resolve-DnsName -Type A -name $remotehost)[-1] $remoteip=$dnsanswer.ipaddress $result.dnstimems = $stopwatch.ElapsedMilliseconds } #Create a TCP Socket to the computer and a port number $result.remotename =$dnsanswer.name $result.remoteip = $remoteip $stopwatch.Restart() $tcpsocket = New-Object Net.Sockets.TcpClient try { write-host " Connect to $($remoteip):$port" -nonewline #$tcpsocket.Connect($computername, $port) $asyncConnect = $tcpsocket.BeginConnect($remoteip, $port,$null,$null) # wait up to tcptimeout if ($asyncConnect.AsyncWaitHandle.WaitOne($tcptimeout, $False)) { } } catch { write-host $_.Exception.Message $result.Status = "ErrConnect" } $result.connecttimems = $stopwatch.ElapsedMilliseconds #test if the socket got connected if(!$tcpsocket.connected) { write-host " Unable to connect" -foregroundcolor red $result.Status = "NoConnection" } else { write-host " Connected" -ForegroundColor Green -NoNewline write-host " Get TCP-Stream" -NoNewline $tcpstream = $tcpsocket.GetStream() write-host " Get SSL-Stream" -NoNewline $sslStream = New-Object System.Net.Security.SslStream($tcpstream,$false,{$true}) # verification callback always true write-host " AuthenticateAsClient:$($tlsmode.ToString()) as $($remotehost)" -nonewline $certcol = new-object System.Security.Cryptography.X509Certificates.X509CertificateCollection try { #$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::"$($tlsmode)", $false) switch ($tlsmode) { "SSL3" {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::Ssl3, $false)} "TLS" {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::tls, $false)} "TLS11" {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::Tls11, $false)} "TLS12" {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::tls12, $false) } "TLS13" {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::tls13, $false) } Default {$sslStream.AuthenticateAsClient($remotehost, $certcol, [System.Net.SecurityProtocolType]::SystemDefault, $false) } } #$sslStream.AuthenticateAsClient($remotehost, $certcol, $tlsprotocol, $false) $result.tlstimems = $stopwatch.ElapsedMilliseconds $result.Status = "AuthTLS$($tlsmode)OK" write-host " AuthTLS$($tlsmode)OK" -ForegroundColor green } catch { $result.tlstimems = $stopwatch.ElapsedMilliseconds write-host " TLSHandshakeFail" -ForegroundColor Yellow write-host "Exception Type: $($_.Exception.GetType().FullName)" -ForegroundColor Red write-host "Exception Message: $($_.Exception.Message)" -ForegroundColor Red $result.Status = "TLSHandshakeFail" } if ($result.Status -eq "AuthTLS$($tlsmode)OK") { try { Write-host " Read the certificate" -nonewline $certinfo = New-Object system.security.cryptography.x509certificates.x509certificate2($sslStream.RemoteCertificate) write-host "done" } catch { Write-host " Unable to read Certificate" $result.Status = "NoCertFound" } if ($result.Status -ne "NoCertFound") { write-host " Parsing Certificate Data" $result.Subject = $certinfo.Subject $result.CN = $certinfo.Subject.split(",") | Where-Object {$_.startswith("CN=")} Write-host " CN= $($result.CN)" $result.NotAfter = $certinfo.NotAfter $result.NotBefore = $certinfo.NotBefore $result.Issuer = $certinfo.Issuer $result.Thumbprint = $certinfo.Thumbprint $result.SerialNumber = $certinfo.SerialNumber $result.SignatureAlgorithmFriendlyName = $certinfo.SignatureAlgorithm.FriendlyName if ($result.SignatureAlgorithmFriendlyName -eq "SHA1RSA") { $result.Status = "WarnSHA1" } elseif (( ($result.NotAfter) - (get-date)).totaldays -lt 0 ) { $result.Status = "Expired" } elseif (( ($result.NotAfter) - (get-date)).totaldays -lt 30 ) { $result.Status = "Warn30Day" } else { $result.Status = "OK" } } } } write-host " Closing Connection" $tcpsocket.close() $result.totaltimems = $stopwatch.ElapsedMilliseconds + $result.dnstimems write-host " Sending Result to Pipeline" $result write-host " Done" } end { $stopwatch.stop() write-host "Get-TCPCert:End" }