[Mono-aspnet-list] WebRequest POST with client certificate
Stefan Kadow
stefan.kadow at cervis.de
Tue Feb 5 16:44:28 UTC 2013
Now, I have a version which works with mono (2.6.7 and 2.10.8) on Linux
and mono (2.10.9) on Windows, but not with .NET
This time I used the SslStream-class for the HTTP-request. It is
important to use a LocalCertificateSelectionCallback method, which will
be called while the ssl-renegotiation!
What I do not understand is the property
sslStream.IsMutuallyAuthenticated, which will allways be false!
The following code (HTTP "POST") runs successful on mono (Linux &
Windows), but throws an excpection with .NET:
static void postSslStream()
{
string hostname = "server.net";
byte[] contentBytes = Encoding.UTF8.GetBytes("<?xml version=\"1.0\"
encoding=\"utf-8\"?><message/>");
StringBuilder headerSB = new StringBuilder();
headerSB.AppendLine("POST /mvc/contr/action HTTP/1.1");
headerSB.Append("Host: ").AppendLine(hostname);
headerSB.AppendLine("Content-Type: text/xml; charset=utf-8");
headerSB.Append("Content-Length:
").Append(contentBytes.Length).AppendLine();
headerSB.AppendLine();
byte[] headerBytes = Encoding.UTF8.GetBytes(headerSB.ToString());
X509Certificate2Collection certColl = new
X509Certificate2Collection();
certColl.Import("certfile.p12", string.Empty,
X509KeyStorageFlags.DefaultKeySet);
TcpClient client = new TcpClient(hostname, 443);
try
{
using (SslStream sslStream = new SslStream(client.GetStream(),
false,
new
RemoteCertificateValidationCallback(RemoteCertificateValidation),
new
LocalCertificateSelectionCallback(LocalCertificateSelection)))
{
sslStream.AuthenticateAsClient(hostname, certColl,
System.Security.Authentication.SslProtocols.Tls, false);
sslStream.Write(headerBytes);
sslStream.Write(contentBytes);
sslStream.Flush();
StreamReader reader = new StreamReader(sslStream);
Console.WriteLine(reader.ReadToEnd());
}
}
finally
{
client.Close();
}
}
public static bool RemoteCertificateValidation(object sender,
X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return (sslPolicyErrors == SslPolicyErrors.None);
}
public static X509Certificate LocalCertificateSelection(Object sender,
string targetHost,
X509CertificateCollection localCertificates, X509Certificate
remoteCertificate, string[] acceptableIssuers)
{
if (remoteCertificate.Issuer == localCertificates[0].Issuer)
return localCertificates[0];
return null;
}
Am 14.01.2013 00:36, schrieb Stefan Kadow:
> 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.
> _______________________________________________
> Mono-aspnet-list mailing list
> Mono-aspnet-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-aspnet-list
>
>
>
More information about the Mono-aspnet-list
mailing list