[Mono-aspnet-list] WebRequest POST with client certificate

Stefan Kadow stefan.kadow at cervis.de
Sun Jan 13 23:36:54 UTC 2013


Hello,
I have a MVC2 web application running on Debian squeeze with Apache 
2.2.16, OpenSSL 0.9.8 and mono 2.6.7. I want to secure the access with 
SSL client certificates, for identification and authorization.

The client programm running on another machine uses the HttpWebRequest 
class for accessing the server with HTTP methods "GET" and "POST". On 
windows machines the client program runs fine using .NET 3.5.
On Linux machines the client program runs only with HTTP method "GET". A 
WebRequest with HTTP method "POST" throws an exception. I tried the 
following code on client machines with Debian squeeze (mono 2.6.7) and 
Debian wheezy (mono 2.10.8).

The following code (HTTP "GET") runs successful on Windows and Linux:
     HttpWebRequest request = (HttpWebRequest)
         WebRequest.Create("https://server.net/mvc/contr/action");

     X509Certificate2Collection certColl =
         new X509Certificate2Collection();
     certColl.Import("certfile.p12", "123",
         X509KeyStorageFlags.Exportable);
     request.ClientCertificates.AddRange(certColl);

     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
     Console.WriteLine(response.StatusDescription);

     Stream responseStream = response.GetResponseStream();
     StreamReader reader = new StreamReader(responseStream);
     Console.WriteLine(reader.ReadToEnd());


The following code (HTTP "POST") runs successful on Windows, but throws 
an excpection on Linux:
     HttpWebRequest request = (HttpWebRequest)
         WebRequest.Create("https://server.net/mvc/contr/action");

     X509Certificate2Collection certColl =
         new X509Certificate2Collection();
     certColl.Import("certfile.p12", "123",
         X509KeyStorageFlags.Exportable);
     request.ClientCertificates.AddRange(certColl);

     string postData = @"<?xml version=\"1.0\" encoding=\"utf-8\"?>
<message/>";
     byte[] byteArray = Encoding.UTF8.GetBytes(postData);
     request.Method = "POST";
     request.ContentType = "text/xml";
     request.ContentLength = byteArray.Length;
     request.KeepAlive = false;  // needed for POST-requests(?)

     Stream requestStream = request.GetRequestStream();
     requestStream.Write(byteArray, 0, byteArray.Length);  // exception
     requestStream.Close();

     HttpWebResponse response = (HttpWebResponse)request.GetResponse();
     Console.WriteLine(response.StatusDescription);

     Stream responseStream = response.GetResponseStream();
     StreamReader reader = new StreamReader(responseStream);
     Console.WriteLine(reader.ReadToEnd());


The exception thrown is:
System.Net.WebException: Error getting response stream (ReadDone1): 
ReceiveFailure ---> System.IO.IOException: The authentication or 
decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The 
authentication or decryption has failed.

Apache error log lists:
[error] Re-negotiation handshake failed: Not accepted by client!?

Apache configuration:
     # mono.security needs old/insecure re-negotiation:
     SSLInsecureRenegotiation on
     <Directory /var/www/bin/mvc>
         SSLVerifyClient require
         SSLVerifyDepth 1
         SSLUserName SSL_CLIENT_S_DN_CN
         SSLOptions +StdEnvVars +ExportCertData +OptRenegotiate
     </Directory>

The server certificate is signed by GeoTrust, the GeoTrust root 
certificate is installed with certmgr.exe in Trust store. The 
self-signed CA certificate, which signed the client certificates is part 
of the pkcs12-file and additionally installed in Trust store, too.
But, the certificates can not be the problem, because the WebRequests 
with HTTP method GET are running fine on Linux client machines.


More information about the Mono-aspnet-list mailing list