From 7963279fc2c3a8cfa6affb70307bac6fa669679c Mon Sep 17 00:00:00 2001
From: David Norman <deekayen@users.noreply.github.com>
Date: Thu, 19 Apr 2018 19:01:48 -0400
Subject: [PATCH] Generate SHA256 signed certificates for WinRM (#36668)

* Generate SHA256 signed certificates

Vulnerability scanners are increasingly reporting SHA-1 signed certificates as a vulnerability on servers. Before this change, -ForceNewSSLCert generates a signature algorithm that openssl shows as sha1WthRSAEncryption for WinRM port 5986. After, this forces certificates to be signed with SHA256, which openssl shows sha256WithRSAEncryption.

Some example SHA-1 deprecations include:
- https://docs.microsoft.com/en-us/security-updates/SecurityAdvisories/2017/4010323
- https://blog.mozilla.org/security/2014/09/23/phasing-out-certificates-with-sha-1-based-signature-algorithms/

Also note that RDP 3389 on Windows 2016 also defaults to a SHA256 certificate.

The specifics were merged from a script mod I found at https://gallery.technet.microsoft.com/scriptcenter/PowerShell-script-to-7a0321b7 intended for Exchange. It also includes a mod to add an alternate DNS listing so the cert contains CN=HOSTNAME plus now also an alternative of the FQDN.

I tested this change on Windows 2008R2, 2012R2, and 2016 Datacenter.

* Keep WinRM cert key length at 4096.

* Remove WinRM cert exportpolicy setting.
---
 .../scripts/ConfigureRemotingForAnsible.ps1   | 34 ++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/examples/scripts/ConfigureRemotingForAnsible.ps1 b/examples/scripts/ConfigureRemotingForAnsible.ps1
index f048219c5c5..caf7d365f3f 100644
--- a/examples/scripts/ConfigureRemotingForAnsible.ps1
+++ b/examples/scripts/ConfigureRemotingForAnsible.ps1
@@ -39,6 +39,7 @@
 # Updated by Dag Wieërs <dag@wieers.com>
 # Updated by Jordan Borean <jborean93@gmail.com>
 # Updated by Erwan Quélin <erwan.quelin@gmail.com>
+# Updated by David Norman <david@dkn.email>
 #
 # Version 1.0 - 2014-07-06
 # Version 1.1 - 2014-11-11
@@ -48,6 +49,7 @@
 # Version 1.5 - 2017-02-09
 # Version 1.6 - 2017-04-18
 # Version 1.7 - 2017-11-23
+# Version 1.8 - 2018-02-23
 
 # Support -Verbose option
 [CmdletBinding()]
@@ -90,11 +92,15 @@ Function New-LegacySelfSignedCert
         [int]$ValidDays = 1095
     )
 
+    $hostnonFQDN = $env:computerName 
+    $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname
+    $SignatureAlgorithm = "SHA256"
+
     $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1"
     $name.Encode("CN=$SubjectName", 0)
 
     $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1"
-    $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
+    $key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider"
     $key.KeySpec = 1
     $key.Length = 4096
     $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
@@ -114,7 +120,33 @@ Function New-LegacySelfSignedCert
     $cert.Issuer = $cert.Subject
     $cert.NotBefore = (Get-Date).AddDays(-1)
     $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)
+
+    $SigOID = New-Object -ComObject X509Enrollment.CObjectId
+    $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value)
+
+    [string[]] $AlternativeName  += $hostnonFQDN
+    $AlternativeName += $hostFQDN
+    $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames
+
+    foreach ($AN in $AlternativeName)
+    {
+        $AltName = New-Object -ComObject X509Enrollment.CAlternativeName
+        $AltName.InitializeFromString(0x3,$AN)
+        $IAlternativeNames.Add($AltName)
+    }
+
+    $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
+    $SubjectAlternativeName.InitializeEncode($IAlternativeNames)
+
+    [String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment")
+    $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage
+    $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage))
+    $KeyUsageObj.Critical = $true
+
+    $cert.X509Extensions.Add($KeyUsageObj)
     $cert.X509Extensions.Add($ekuext)
+    $cert.SignatureInformation.HashAlgorithm = $SigOID
+    $CERT.X509Extensions.Add($SubjectAlternativeName)
     $cert.Encode()
 
     $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1"