4

I have to do a proof of concept and thus far I'm finding primarily old articles that reference IIS6 which isn't helping.

In short I have the following requirements.

I need to secure one file/page and this one file/page only using a client certificate. The rest of the site does need to continue operating under SSL but doesn't require client certificate, just this one file. User mapping is forbidden as mapping will be done programatically via C#/VB.NET.

Now I know this shouldn't be hard. I mean I should have access to the Request.ClientCertificate property but my problem is that in my testing I can't get a client certificate to travelling along the wire.

I've set IIS on one folder ( just to make my life simple ) require SSL and accept client certs as well as require client certs but all i get from iis once visiting the page is HTTP/1.1 403 Forbidden. I never get asked to choose a client certificate to send to the server it just spews all over my request and drops it.

It gets even weirder when I'm using some code to test this. In this client code the CertPolicy class just returns true from a method to ignore cert errors and test.cer is a self signed cert made from using MakeCert. Just to make it clear though, only the client cert if self signed, the main cert is properly signed, but i play with fiddler alot and I haven't trusted that cert so that's why I have the hacky callback.

Dim Cert As X509Certificate = X509Certificate.CreateFromCertFile("Cert\test.cer")
' Handle any certificate errors on the certificate from the server.
ServicePointManager.CertificatePolicy = New CertPolicy()
' You must change the URL to point to your Web server.
Dim Request As HttpWebRequest = DirectCast(WebRequest.Create("https://local.domain.com/Cert/Server/"), HttpWebRequest)
Request.ClientCertificates.Add(Cert)
Request.UserAgent = "Client Cert Sample"
Request.Method = "GET"

Dim sr As StreamReader
Using Response As HttpWebResponse = DirectCast(Request.GetResponse, HttpWebResponse)
    ' Print the repsonse headers.
    output.AppendFormat("{0}\r\n", Response.Headers)
    output.AppendLine()
    ' Get the certificate data.
    sr = New StreamReader(Response.GetResponseStream, Encoding.Default)
    Dim count As Integer
    Dim ReadBuf() As Char = New Char((1024) - 1) {}
    Do
        count = sr.Read(ReadBuf, 0, 1024)
        If Not 0 = count Then
            output.AppendLine(New String(ReadBuf))
        End If
    Loop While (count > 0)
End Using

The target page just returns the number of certs attached, which always returns if i set IIS to accept or ignore client certs but not required the.

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    Dim cs As HttpClientCertificate = Request.ClientCertificate
    Response.Write(cs.Count)
    Response.End()
End Sub

If anyone can help me find out how to configure IIS7.5 to allow client certs to be attached to a request and just passed through that would be great.

cdmdotnet
  • 1,663
  • 3
  • 17
  • 22

2 Answers2

3

This is an old question but I found it while searching for my own answers and figured it should be answered. In the web.config for the web site, to enable client certificates, you must first make sure that authentication module is installed, then enable the feature:

<location path="yourpath">
  <system.webServer>
    <security>
      <access sslFlags="Ssl, SslNegotiateCert"/> <!-- or SslRequireCert --> 
      <authentication>
        <iisClientCertificateMappingAuthentication enabled="true" 
            oneToOneCertificateMappingsEnabled="true"> 
            <!-- or manyToOneCertificateMappingsEnabled="true" -->
        </iisClientCertificateMappingAuthentication>
      </authentication>
    </security>
  </system.webServer>
</location>

Then you add the one-to-one or many-to-one mappings inside of the iisClientCertificateMappingAuthentication element.

Jacob
  • 77,566
  • 24
  • 149
  • 228
  • I'm finding that if you specify `SslRequireCert`, you must *also* specify `SslNegotiateCert`. – AakashM Nov 07 '12 at 08:58
  • looks like you are on to something. Could you check http://stackoverflow.com/questions/14407666/how-do-i-implement-client-certificate-authentication-the-right-way and maybe provide the necessary information I am looking for? Important for me related to this answer is the importance of this ClientCertificateMappingAuthentication-node in the web.config for the serverpart of the configuration. – Guillaume Schuermans Jan 18 '13 at 22:26
2

When the server asks the browser for the client certificate, it sends a list of certificate authorities it trusts. The browser then filters the available certificates based upon this information in order to display only relevant certificates (those issued by CAs the server trusts) in the certificate choice dialog.

(At least this is how Internet Explorer works; I don't know if other browsers perform such filtering.)

Therefore the client cert should not be self signed, but 1) should be issued by a certificate authority, 2) the certificate of that certificate authority should be installed on the server (in the Trusted Root Certificate Authorities store of the Local Machine account).

For testing purposes, you may set up your own CA, just make sure its certificate is installed on the server.

Jakub Berezanski
  • 1,053
  • 9
  • 13