Attach SSL certificate to site in IIS programmatically

0

I've searching for a solution to my problem for a couple days now and have found almost nothing. Here's the issue: I need to attach an SSL certificate to a website in IIS 6. I can set the https binding but every time I try to set the certificate's thumbprint, and the certificate store, for the binding I get COM Exceptions. Here's my code.

    Private Const UnformattedMetabasePathForSiteProperties As String = "IIS://localhost/W3SVC/{0}"
    Private metabasePath As String
    Public Sub BindCertificateToSite(iisSiteId As Integer, ByVal aCertificate As X509Certificate2) Implements IIisSslHandler.BindCertificatetoSite
        metabasePath = UnformattedMetabasePathForSiteProperties.FormatIt(iisSiteId)
        Dim ipAddress As String = GetProperty(metabasePath, "ServerBindings")
        Contract.Require(Not String.IsNullOrEmpty(ipAddress), New Exception("Failed to find the site's http binding and IP address. Can not bind certificate to site."))
        ipAddress = ipAddress.Split(":")(0)
        SetProperty(metabasePath, "SecureBindings", ipAddress & ":443:", True)
        SetProperty(metabasePath, "SSLStoreName", "MY", True)
        SetBinaryProperty(metabasePath, "SSLCertHash", aCertificate.Thumbprint, True)
    End Sub

    Private Sub SetProperty(ByVal metabasePath As String, ByVal propertyName As String, ByVal newValue As Object, clearCurrentValue As Boolean)
        Dim path As DirectoryEntry
        path = New DirectoryEntry(metabasePath)
        If clearCurrentValue Then path.Properties(propertyName).Clear()
        path.Properties(propertyName).Add(newValue)
        path.CommitChanges()
    End Sub

    Private Sub SetBinaryProperty(ByVal metabasePath As String, ByVal propertyName As String, ByVal newValue As Object, clearCurrentValue As Boolean)
        Dim path As DirectoryEntry
        path = New DirectoryEntry(metabasePath)
        Dim propValues As PropertyValueCollection
        propValues = path.Properties(propertyName)
        If clearCurrentValue Then propValues.Clear()
        propValues.Add(newValue)
        path.CommitChanges()
    End Sub

The exceptions I get ocurrs at the propValues.Add call for both the SSLStoreName and the SSLCertHash

SSLStoreName exception: An exception of type 'System.Runtime.InteropServices.COMException' occurred in System.DirectoryServices.dll but was not handled in user code. Additional information: A specified logon session does not exist. It may already have been terminated. (Exception from HRESULT: 0x80070520)

SSLCertHash Exception: An exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll but was not handled in user code. Additional information: Exception from HRESULT: 0x8000500C

I have found other questions here on the stack and other sites on the net that seem to point to a flaw in the .Net framework when it comes to IIS 6 but I'm hoping that's not the case here. So my question: Why isn't this working and how can I fix it?

vb.net
ssl-certificate
iis-6
asked on Stack Overflow Apr 8, 2016 by Richard Barker • edited Oct 11, 2018 by Cœur

1 Answer

0

Ok so i finally got this to work. As such I'm posting this code for future stackers and myself.

Private Const UnformattedMetabasePathForSiteProperties As String = "IIS://localhost/W3SVC/{0}"
Private metabasePath As String
Public Sub BindCertificateToSite(iisSiteId As Integer, ByVal aCertificate As X509Certificate2) Implements IIisSslHandler.BindCertificatetoSite
    metabasePath = UnformattedMetabasePathForSiteProperties.FormatIt(iisSiteId)
    Dim ipAddress As String = GetProperty(metabasePath, "ServerBindings")
    Contract.Require(Not String.IsNullOrEmpty(ipAddress), New Exception("Failed to find the site's http binding and IP address. Can not bind certificate to site."))
    ipAddress = ipAddress.Split(":")(0)
    SetProperty(metabasePath, "SecureBindings", ipAddress & ":443:", True)
    SetProperty(metabasePath, "SSLStoreName", "MY", True)
    SetBinaryProperty(metabasePath, "SSLCertHash", aCertificate.GetCertHash(), True)
End Sub

Private Sub SetProperty(ByVal metabasePath As String, ByVal propertyName As String, ByVal newValue As Object, clearCurrentValue As Boolean)
    Dim path As DirectoryEntry
    path = New DirectoryEntry(metabasePath)
    If clearCurrentValue Then path.Properties(propertyName).Clear()
    path.Invoke("Put", propertyName, newValue)
    path.CommitChanges()
End Sub

Private Sub SetBinaryProperty(ByVal metabasePath As String, ByVal propertyName As String, ByVal newValue As Object, clearCurrentValue As Boolean)
    Dim path As DirectoryEntry
    path = New DirectoryEntry(metabasePath)
    Dim propValues As PropertyValueCollection
    propValues = path.Properties(propertyName)
    If clearCurrentValue Then propValues.Clear()
    path.Invoke("Put", propertyName, newValue)
    path.CommitChanges()
End Sub
answered on Stack Overflow Apr 8, 2016 by Richard Barker

User contributions licensed under CC BY-SA 3.0