I am trying to use HttpWebRequest to query a remote server with nginx. I need to provide a client certificate to complete the connection.
I do the following:
Dim Request As HttpWebRequest = DirectCast(WebRequest.Create(Url), HttpWebRequest) Dim Cert = SSL.GetClientCertificate() Request.ClientCertificates.Clear() Request.ClientCertificates.Add(Cert) Dim Response As WebResponse = Request.GetResponse()
( SSL.GetClientCertificate is just a helper method that opens the My repository on the local computer and extracts the corresponding certificate (like X509Certificate2 ). The correct certificate is returned. I also tried just loading the certificate from the file with the same results.)
Be that as it may, when I get to Dim Response As... and actually try to open the connection, I get 400 Bad Request returned with the following body:
400 Bad Request No required SSL certificate was sent ----------------------------------- nginx/1.0.10
We use our own CA, which has a certificate in LocalMachine\TrustedRootCertificationAuthorities on my machine. The client certificate is valid but not verified because our CA does not disclose the OCSP endpoint. If I create an X509Chain and ask to check the chain without checking for cancellation, everything will pass.
So my question is: why the certificate is not sent with the request? I do not think that this should be an attempt to verify the client certificate before sending it (which is the job of the servers).
I will not sink you in Wireshark logs, but the client does not send the certificate. In short, I get ...
- [Out] Hello client
- [In] Hello Server
- [In] Certificate
- [In] Hello Done Server
- [Out] Certificate, Exchange Client Exchange, Change Cipher Spec, Encrypted Handshake Message
- [In] Change Cipher Spec, encrypted confirmation message
- [Out] Application Data (Presumably GET Request)
- [In] Application data (presumably 400)
- [In] Encrypted Alert (terminates the channel)
I think nginx is doing something smart, where instead of dying when I cannot send the certificate, it restarts to let it send the 400 response body (instead of not creating the channel in the first place)
In any case, I am not sending a certificate, which is the real problem. Does anyone know why?
In case this helps, nginx logs do not insist on sending a certificate (unlike a certificate that is not valid):
2012/11/22 14:16:26 [info] 27755 # 0: * Client 799 sent an unnecessary SSL certificate when reading client request headers, client: 10.0.0.200, server: 10.0.0.100, request: "GET / state HTTP /1.1 ", host:" 10.0.0.100 "
Please do not use the code below - it is inefficient, unreliable and was used only for testing
Re: Certificate receipt:
Public Shared Function GetClientCertificate() As X509Certificate2 Dim Store As New X509Store(StoreName.My, StoreLocation.LocalMachine) Dim Ret As X509Certificate2 = Nothing Try Store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly) For Each Certificate In Store.Certificates If Certificate.SubjectName.Name = "The subjectname of our certificate" Then Ret = Certificate Exit For End If Next Finally Store.Close() End Try Return Ret End Function