SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

Remote Desktop で使用する証明書を同一の拇印で重複インポートした場合の挙動について

leave a comment

リモートデスクトップで自己証明証明書ではなく、証明機関から発行された証明書を使うことがあるかと思います。

同一の拇印の証明書を複数回インポートした場合、MMC の証明書のスナップインでは、一つの証明書しか表示されないのですが、秘密キーについては新しくなっているようでそれにより、接続ができない現象があったのでまとめておきたいと思います。

リモートデスクトップの証明書として使用する場合は、以下のようなコマンドを実行することで設定が可能です。

Import-PfxCertificate -CertStoreLocation "cert:\LocalMachine\My" -FilePath <pfx ファイル> -Password (ConvertTo-SecureString -String <パスワード> -AsPlainText -Force)
$path = (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").__path 
Set-WmiInstance -Path $path -argument @{SSLCertificateSHA1Hash=<証明書拇印>}

上記のコマンドを二回実行すると、リモートデスクトップで接続しようとすると、以下のメッセージが表示され、接続ができないという現象が発生することがあります。

image

この際、接続先の環境のイベントログには以下のような「Schannel : 36870」のエラーが出力されます。

image

類似のエラーを検索すると、いろいろとヒットすると思うのですが、今回の事象の場合は、使用している証明書の秘密キーのアクセス許可として「NETWORK SERVICE」が追加されていないことに起因しています。

冒頭のコマンドですが、インポートとリモートデスクトップの設定の 2 種類の設定を行っています。

署名所のインポートについては、「Localmachine\My」に証明書をストアする処理になります。

同一の証明書をインポートした場合、MMC 上は表示は変わらないのですが、ファイル配置としては秘密キーの再配置が実施されているようで、「C:\ProgramData\Microsoft\Crypto」に秘密キーがインポートをするたびに新規に配置されます。

# RSA\MachineKeys に配置されるかと。私の環境ではなぜか、Keys に配置されてしまっていますが。

その後 Set-WmiInstance を実行することで、指定した証明書の拇印をレジストリに登録すると同時に、秘密キーに対して「NETWORK SERVICE」の読み取り許可を設定しているのですが、すでに設定されている証明書の拇印に対して再実行をしても、アクセス権の再設定が実行されていないようで、

  • 秘密キーは生成されているが、NETWORK SERVICE のアクセス権が付与されていない状態

となっており、権限が不足しているため、接続ができないという状態となってしまっているようです。

秘密キーに対して直接アクセス権を付与するか、レジストリを一度消してから再設定することで、アクセスができるようになるかと。

# 秘密キーのファイルについては、証明書の MMC から、該当の証明書を右クリックして、「すべてタスク→秘密キーの管理」から設定変更可能です。

  • 署名署のインポートをする際に、X509Certificate2 クラス で読み込もうとしている証明書の拇印を取得し、それで証明書ストアを確認し、存在していない場合はインポートをする
  • SSLCertificateSHA1Hash を一度削除して再設定

というようなことを実施しておけば、重複インポートを防ぎ、アクセス権を設定するという処理を組むことができました。

$certpath = "<PFX のファイルパス>"
$certpass = "<PFX のパスワード>"

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $certpath, $certpass, ([System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet)

if((Get-ChildItem Cert:\LocalMachine\My).Thumbprint -notcontains $cert.Thumbprint){
    Write-host "Cert Import"
    Import-PfxCertificate -CertStoreLocation "cert:\LocalMachine\My" -FilePath $certpath -Password (ConvertTo-SecureString -String $certpass -AsPlainText -Force)
}

if((Get-ItemProperty 'registry::\HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp').SSLCertificateSHA1Hash -ne $null){
    Remove-ItemProperty "registry::\HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Name SSLCertificateSHA1Hash
}
$path = (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").__path 
Set-WmiInstance -Path $path -argument @{SSLCertificateSHA1Hash="$($cert.Thumbprint)"}

$cert.Dispose()

Written by masayuki.ozawa

8月 19th, 2016 at 8:08 am

Posted in Remote Desktop

Tagged with

Leave a Reply

*