* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Mono.Security / Test / tools / postecho / postecho.cs
1 //
2 // postecho.cs: TLS/SSL Post Echo Test Program
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier  <gonzalo@ximian.com>
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2005 Novell (http://www.novell.com)
9 //
10
11 using System;
12 using System.IO;
13 using System.Net;
14 using System.Net.Sockets;
15 using System.Text;
16 using System.Security.Cryptography.X509Certificates;
17 using Mono.Security.Protocol.Tls;
18
19 class PostEcho {
20
21         static void Help ()
22         {
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");
27         }
28
29         static string PostWeb (string url, byte[] buffer)
30         {
31                 ServicePointManager.CertificatePolicy = new TestCertificatePolicy ();
32
33                 string postdata = "TEST=";
34                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
35                 req.Method = "POST";
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);
42                 output.Close ();
43                 HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
44                 StreamReader reader = new StreamReader (response.GetResponseStream ());
45                 return reader.ReadToEnd ();
46         }
47
48         static string PostStream (Mono.Security.Protocol.Tls.SecurityProtocolType protocol, string url, byte[] buffer)
49         {
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";
55                 post += "TEST=";
56                 byte[] bytes = Encoding.Default.GetBytes (post);
57
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);
65
66                 ssl.Write (bytes, 0, bytes.Length);
67                 ssl.Write (buffer, 0, buffer.Length);
68                 ssl.Flush ();
69
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);
75         }
76
77         static int Main (string[] args)
78         {
79                 if (args.Length < 1) {
80                         Help ();
81                         return 2;
82                 }
83
84                 string url = args [0];
85                 int size = 1024;
86                 bool ssl = true;
87                 Mono.Security.Protocol.Tls.SecurityProtocolType protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Tls;
88
89                 if (args.Length > 1) {
90                         for (int i=1; i < args.Length; i++) {
91                                 switch (args [i].ToLower ()) {
92                                 case "--ssl3":
93                                         ssl = true;
94                                         protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Ssl3;
95                                         break;
96                                 case "--tls":
97                                 case "--tls1":
98                                         ssl = true;
99                                         protocol = Mono.Security.Protocol.Tls.SecurityProtocolType.Tls;
100                                         break;
101                                 case "--web":
102                                         ssl = false;
103                                         break;
104                                 default:
105                                         size = Int32.Parse (args [i]);
106                                         break;
107                                 }
108                         }
109                 }
110
111                 // prepare test buffer
112                 byte[] data = new byte[size];
113                 for (int i = 0; i < size; i++)
114                         data[i] = 65;
115
116                 string result = (ssl ? PostStream (protocol, url, data) : PostWeb (url, data));
117
118                 if (data.Length != result.Length) {
119                         Console.WriteLine ("Invalid length {0}. Expected {1}", result.Length, data.Length);
120                         return 1;
121                 }
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]);
125                                 return 1;
126                         }
127                 }
128                 Console.WriteLine ("Result OK (length: {0})", result.Length);
129                 return 0;
130         }
131
132         private static void ShowCertificateError (int error)
133         {
134                 string message = null;
135                 switch (error)
136                 {
137                         case -2146762490:
138                                 message = "CERT_E_PURPOSE 0x800B0106";
139                                 break;
140                         case -2146762481:
141                                 message = "CERT_E_CN_NO_MATCH 0x800B010F";
142                                 break;
143                         case -2146869223:
144                                 message = "TRUST_E_BASIC_CONSTRAINTS 0x80096019";
145                                 break;
146                         case -2146869232:
147                                 message = "TRUST_E_BAD_DIGEST 0x80096010";
148                                 break;
149                         case -2146762494:
150                                 message = "CERT_E_VALIDITYPERIODNESTING 0x800B0102";
151                                 break;
152                         case -2146762495:
153                                 message = "CERT_E_EXPIRED 0x800B0101";
154                                 break;
155                         case -2146762486:
156                                 message = "CERT_E_CHAINING 0x800B010A";
157                                 break;
158                         case -2146762487:
159                                 message = "CERT_E_UNTRUSTEDROOT 0x800B0109";
160                                 break;
161                         default:
162                                 message = "unknown (try WinError.h)";
163                                 break;
164                 }
165                 Console.WriteLine ("Error #{0}: {1}", error, message);
166         }
167
168         private static bool CertificateValidation (X509Certificate certificate, int[] certificateErrors)
169         {
170                 if (certificateErrors.Length > 0)
171                 {
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)
178                         {
179                                 ShowCertificateError (error);
180                         }
181                 }
182                 // whatever the reason we do not stop the SSL connection
183                 return true;
184         }
185
186         public class TestCertificatePolicy : ICertificatePolicy {
187
188                 public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
189                 {
190                         if (error != 0) {
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);
195
196                                 ShowCertificateError (error);
197                         }
198                         // whatever the reason we do not stop the SSL connection
199                         return true;
200                 }
201         }
202 }
203