2 // postecho.cs: TLS/SSL Post Echo Test Program
5 // Gonzalo Paniagua Javier <gonzalo@ximian.com>
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // (C) 2005 Novell (http://www.novell.com)
14 using System.Net.Sockets;
16 using System.Security.Cryptography.X509Certificates;
17 using Mono.Security.Protocol.Tls;
23 Console.WriteLine ("postecho url [size] [--web | --ssl3 | --tls1]");
24 Console.WriteLine (" default size is 1024 (bytes)");
25 Console.WriteLine (" default mode is --tls1");
26 Console.WriteLine ("* a server side script must be installed to run postecho");
29 static string PostWeb (string url, byte[] buffer)
31 ServicePointManager.CertificatePolicy = new TestCertificatePolicy ();
33 string postdata = "TEST=";
34 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
36 req.ContentType = "application/x-www-form-urlencoded";
37 req.ContentLength = 5 + buffer.Length;
38 Stream output = req.GetRequestStream ();
39 byte [] bytes = Encoding.Default.GetBytes (postdata);
40 output.Write (bytes, 0, bytes.Length);
41 output.Write (buffer, 0, buffer.Length);
43 HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
44 StreamReader reader = new StreamReader (response.GetResponseStream ());
45 return reader.ReadToEnd ();
48 static string PostStream (Mono.Security.Protocol.Tls.SecurityProtocolType protocol, string url, byte[] buffer)
50 Uri uri = new Uri (url);
51 string post = "POST " + uri.AbsolutePath + " HTTP/1.0\r\n";
52 post += "Content-Type: application/x-www-form-urlencoded\r\n";
53 post += "Content-Length: " + (buffer.Length + 5).ToString () + "\r\n";
54 post += "Host: " + uri.Host + "\r\n\r\n";
56 byte[] bytes = Encoding.Default.GetBytes (post);
58 IPHostEntry host = Dns.Resolve (uri.Host);
59 IPAddress ip = host.AddressList [0];
60 Socket socket = new Socket (ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
61 socket.Connect (new IPEndPoint (ip, uri.Port));
62 NetworkStream ns = new NetworkStream (socket, false);
63 SslClientStream ssl = new SslClientStream (ns, uri.Host, false, protocol);
64 ssl.ServerCertValidationDelegate += new CertificateValidationCallback (CertificateValidation);
66 ssl.Write (bytes, 0, bytes.Length);
67 ssl.Write (buffer, 0, buffer.Length);
70 StreamReader reader = new StreamReader (ssl, Encoding.UTF8);
71 string result = reader.ReadToEnd ();
72 int start = result.IndexOf ("\r\n\r\n") + 4;
73 start = result.IndexOf ("\r\n\r\n") + 4;
74 return result.Substring (start);
77 static int Main (string[] args)
79 if (args.Length < 1) {
84 string url = args [0];
87 Mono.Security.Protocol.Tls.SecurityProtocolType protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Tls;
89 if (args.Length > 1) {
90 for (int i=1; i < args.Length; i++) {
91 switch (args [i].ToLower ()) {
94 protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Ssl3;
99 protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Tls;
105 size = Int32.Parse (args [i]);
111 // prepare test buffer
112 byte[] data = new byte[size];
113 for (int i = 0; i < size; i++)
116 string result = (ssl ? PostStream (protocol, url, data) : PostWeb (url, data));
118 if (data.Length != result.Length) {
119 Console.WriteLine ("Invalid length {0}. Expected {1}", result.Length, data.Length);
122 for (int i = 0; i < result.Length; i++) {
123 if (result[i] != 'A') {
124 Console.WriteLine ("Error at position #{0} - received '{1}'", i, result[i]);
128 Console.WriteLine ("Result OK (length: {0})", result.Length);
132 private static void ShowCertificateError (int error)
134 string message = null;
138 message = "CERT_E_PURPOSE 0x800B0106";
141 message = "CERT_E_CN_NO_MATCH 0x800B010F";
144 message = "TRUST_E_BASIC_CONSTRAINTS 0x80096019";
147 message = "TRUST_E_BAD_DIGEST 0x80096010";
150 message = "CERT_E_VALIDITYPERIODNESTING 0x800B0102";
153 message = "CERT_E_EXPIRED 0x800B0101";
156 message = "CERT_E_CHAINING 0x800B010A";
159 message = "CERT_E_UNTRUSTEDROOT 0x800B0109";
162 message = "unknown (try WinError.h)";
165 Console.WriteLine ("Error #{0}: {1}", error, message);
168 private static bool CertificateValidation (X509Certificate certificate, int[] certificateErrors)
170 if (certificateErrors.Length > 0)
172 Console.WriteLine (certificate.ToString (true));
173 // X509Certificate.ToString(true) doesn't show dates :-(
174 Console.WriteLine ("\tValid From: {0}", certificate.GetEffectiveDateString ());
175 Console.WriteLine ("\tValid Until: {0}{1}", certificate.GetExpirationDateString (), Environment.NewLine);
176 // multiple errors are possible using SslClientStream
177 foreach (int error in certificateErrors)
179 ShowCertificateError (error);
182 // whatever the reason we do not stop the SSL connection
186 public class TestCertificatePolicy : ICertificatePolicy {
188 public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
191 Console.WriteLine (certificate.ToString (true));
192 // X509Certificate.ToString(true) doesn't show dates :-(
193 Console.WriteLine ("\tValid From: {0}", certificate.GetEffectiveDateString ());
194 Console.WriteLine ("\tValid Until: {0}{1}", certificate.GetExpirationDateString (), Environment.NewLine);
196 ShowCertificateError (error);
198 // whatever the reason we do not stop the SSL connection