Skip to content

Instantly share code, notes, and snippets.

@stypr stypr/rdp.ps1
Last active Aug 17, 2019

Embed
What would you like to do?
How to convert HTTPS Certificates for RDP auth (using Caddy)
# derived from http://stackoverflow.com/questions/40046916/how-to-grant-permission-to-user-on-certificate-private-key-using-powershell
param (
[string]$certThumbprint = "NothingToDoHere"
)
$serviceAccount = 'NETWORK SERVICE'
$permissionType = 'Read'
try
{
Write-Host "Thumbprint: $certThumbprint"
#Clear Existing Variables
$cert = ''
$keyFullPath = ''
Write-Host "--------------------------"
Write-Host "Server: $env:ComputerName" -ForegroundColor Cyan
Write-Host "Finding Certificate..." -ForegroundColor Green
#Get Certificate
$cert = Get-ChildItem -Path cert:\LocalMachine\My | Where-Object {$_.Thumbprint -eq ($certThumbprint -replace '\s','')}
If ($cert -ne $null -and $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName -ne $null)
{
# Get Location of the machine related keys
$keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\";
$keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName;
$keyFullPath = $keyPath + $keyName;
Write-Host "Found Certificate..." -ForegroundColor Green
Write-Host "Granting access to $serviceAccount..." -ForegroundColor Green
#Grant Full Control to account listed in $serviceAccount
$acl = (Get-Item $keyFullPath).GetAccessControl('Access') #Get Current Access
$buildAcl = New-Object System.Security.AccessControl.FileSystemAccessRule($serviceAccount,$permissionType,"Allow") #Build Access Rule
$acl.SetAccessRule($buildAcl) #Add Access Rule
Set-Acl $keyFullPath $acl #Save Access Rules
Write-Host "Access granted to $serviceAccount..." -ForegroundColor Green
Write-Host "--------------------------"
}
Else {
Write-Host "Unable to find Certificate that matches thumbprint $certThumbprint or the private key is missing..." -ForegroundColor Red
Write-Host "--------------------------"
}
}
catch
{
Write-Host "Unable to grant access to $serviceAccount..." -ForegroundColor Yellow
Write-Host "--------------------------"
throw $_;
}
#!/usr/bin/python -u
#-*- coding: utf-8 -*-
__author__ = "Harold Kim"
__email__ = "root@stypr.com"
import os
import sys
import time
import datetime
import hashlib
import _winreg
def list_installed_certs():
""" List installed Certificates (return type list) """
cert = []
# get sha1sum of installed certficates
_cert_installed = []
_cert_directory ='Software\\Microsoft\\SystemCertificates\\MY\\Certificates'
_cert_list = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, _cert_directory)
i = 0
try:
while True:
_cert_installed.append([_winreg.EnumKey(_cert_list, i),])
i += 1
except WindowsError:
pass
# get blobs of installed certificates
for i in xrange(len(_cert_installed)):
_cert_info = _winreg.OpenKey(
_winreg.HKEY_LOCAL_MACHINE,
os.path.join(_cert_directory, _cert_installed[i][0])
)
j = 0
try:
while True:
_cert_blob = _winreg.EnumValue(_cert_info, j)[1]
_cert_installed[i].append(_cert_blob)
j += 1
except WindowsError:
pass
# get info of installed certificates
for i in xrange(len(_cert_installed)):
_blob_temp = os.path.join(
os.environ['TEMP'],
hashlib.sha1(_cert_installed[i][1]).hexdigest()
)
_file_temp = open(_blob_temp, 'wb')
_file_temp.write(_cert_installed[i][1])
_file_temp.close()
_cert_result = os.popen("certutil -dump " + _blob_temp).read()
# parse_cert_result
_cert_notbefore = _cert_result.split("NotBefore: ")[1].split(" ")[0]
_cert_notafter = _cert_result.split("NotAfter: ")[1].split(" ")[0]
# 2nd hierachy
_cert_cn = _cert_result.split("CN=")[2].split(",")[0].split("\n")[0]
_cert_sha1sum = _cert_result.split("(sha1):")[1] \
.split("\n")[0].replace(" ", "")
if _cert_installed[i][0].lower() == _cert_sha1sum.lower():
cert.append({
'before': time.mktime(
datetime.datetime.strptime(
_cert_notbefore, "%Y-%m-%d"
).timetuple()
),
'after': time.mktime(
datetime.datetime.strptime(
_cert_notafter, "%Y-%m-%d"
).timetuple()
),
'CN': _cert_cn,
'sha1': _cert_sha1sum.lower(),
})
os.remove(_blob_temp)
return cert
def get_caddy_cert_directory(domain):
""" get caddy certificate directory """
for root, dirs, files in os.walk(
os.path.join(os.environ['HOMEPATH'], ".caddy")):
for _file in files:
if _file.endswith("crt") and _file.startswith(domain_name):
return root
return False
def sha1sum_from_openssl(filename):
""" parse sha1sum from openssl result """
_cmd = "openssl x509 -in %s -noout -fingerprint"
_data = os.popen(_cmd % (filename,)).read()
try:
_data = _data.split("=")[1].split("\n")[0].replace(":", "").lower()
if not _data:
return False
except:
return False
return _data
def parse_certificate(result, domain_name):
for _cert in result:
if _cert['CN'] == domain_name:
return _cert
return False
if __name__ == "__main__":
domain_name = "your.caddy-domain.tld"
# get caddy cert directory
caddy_certificate = get_caddy_cert_directory(domain_name)
if not caddy_certificate:
print("Caddy does not have your certificate!")
sys.exit(-1)
_installed = parse_certificate(list_installed_certs(), domain_name)
_cert = os.path.join(caddy_certificate, domain_name + '.crt')
_priv = os.path.join(caddy_certificate, domain_name + '.key')
_pfx = os.path.join(caddy_certificate, domain_name + '.pfx')
_sha1 = sha1sum_from_openssl(_cert)
if _installed:
if _sha1 == _installed['sha1']:
print("Not required to trigger any events.")
sys.exit(-1)
# x509 -> pkcs12
_cmd = "openssl pkcs12 -export -out %s -inkey %s -in %s -passout pass:"
_convert = os.popen(_cmd % (_pfx, _priv, _cert,)).read()
# remove pkcs12
_cmd = "certutil -delstore my %s"
_remove = os.popen(_cmd % (domain_name,)).read()
# install pkcs12
_cmd = "certutil -p \"\" -importPFX my %s NoProtect"
_install = os.popen(_cmd % (_pfx,)).read()
print(_install)
# apply RDP key
_cmd = "wmic /namespace:\\root\cimv2\TerminalServices PATH "
_cmd += "Win32_TSGeneralSetting Set SSLCertificateSHA1Hash=\"‎‎%s\""
_apply = os.popen(_cmd % (_sha1,)).read()
# give ACL to RDP -- refer to rdp.ps1 (Powershell script)
_acl = os.popen("Powershell -File rdp.ps1 %s" % (_sha1,)).read()
print("Done as expected!")
@stypr

This comment has been minimized.

Copy link
Owner Author

commented Jul 19, 2017

Someone sent me a bug request mail for this. Please update the code with the following:

	_cmd = "wmic /namespace:\\\\root\\cimv2\\TerminalServices PATH "
	_cmd += "Win32_TSGeneralSetting Set SSLCertificateSHA1Hash=\"‎‎%s\""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.