Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / SslServerStream.cs
1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
3
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24
25 using System;
26 using System.Collections;
27 using System.IO;
28 using System.Net;
29 using System.Net.Sockets;
30 using System.Security.Cryptography;
31 using System.Security.Cryptography.X509Certificates;
32
33 using Mono.Security.Protocol.Tls.Handshake;
34
35 namespace Mono.Security.Protocol.Tls
36 {
37 #if INSIDE_SYSTEM
38         internal
39 #else
40         public
41 #endif
42         class SslServerStream : SslStreamBase
43         {
44                 #region Internal Events
45                 
46                 internal event CertificateValidationCallback    ClientCertValidation;
47                 internal event PrivateKeySelectionCallback              PrivateKeySelection;
48                 
49                 #endregion
50
51                 #region Properties
52
53                 public X509Certificate ClientCertificate
54                 {
55                         get
56                         {
57                                 if (this.context.HandshakeState == HandshakeState.Finished)
58                                 {
59                                         return this.context.ClientSettings.ClientCertificate;
60                                 }
61
62                                 return null;
63                         }
64                 }
65
66                 #endregion
67
68                 #region Callback Properties
69
70                 public CertificateValidationCallback ClientCertValidationDelegate 
71                 {
72                         get { return this.ClientCertValidation; }
73                         set { this.ClientCertValidation = value; }
74                 }
75
76                 public PrivateKeySelectionCallback PrivateKeyCertSelectionDelegate
77                 {
78                         get { return this.PrivateKeySelection; }
79                         set { this.PrivateKeySelection = value; }
80                 }
81
82                 #endregion
83
84                 public event CertificateValidationCallback2 ClientCertValidation2;
85                 #region Constructors
86
87                 public SslServerStream(
88                         Stream                  stream, 
89                         X509Certificate serverCertificate) : this(
90                         stream, 
91                         serverCertificate, 
92                         false, 
93                         false, 
94                         SecurityProtocolType.Default)
95                 {
96                 }
97
98                 public SslServerStream(
99                         Stream                  stream,
100                         X509Certificate serverCertificate,
101                         bool                    clientCertificateRequired,
102                         bool                    ownsStream): this(
103                         stream, 
104                         serverCertificate, 
105                         clientCertificateRequired, 
106                         ownsStream, 
107                         SecurityProtocolType.Default)
108                 {
109                 }
110
111                 public SslServerStream(
112                         Stream                  stream,
113                         X509Certificate serverCertificate,
114                         bool                    clientCertificateRequired,
115                         bool                    requestClientCertificate,
116                         bool                    ownsStream)
117                                 : this (stream, serverCertificate, clientCertificateRequired, requestClientCertificate, ownsStream, SecurityProtocolType.Default)
118                 {
119                 }
120
121                 public SslServerStream(
122                         Stream                                  stream,
123                         X509Certificate                 serverCertificate,
124                         bool                                    clientCertificateRequired,
125                         bool                                    ownsStream,
126                         SecurityProtocolType    securityProtocolType)
127                         : this (stream, serverCertificate, clientCertificateRequired, false, ownsStream, securityProtocolType)
128                 {
129                 }
130
131                 public SslServerStream(
132                         Stream                                  stream,
133                         X509Certificate                 serverCertificate,
134                         bool                                    clientCertificateRequired,
135                         bool                                    requestClientCertificate,
136                         bool                                    ownsStream,
137                         SecurityProtocolType    securityProtocolType)
138                         : base(stream, ownsStream)
139                 {
140                         this.context = new ServerContext(
141                                 this,
142                                 securityProtocolType,
143                                 serverCertificate,
144                                 clientCertificateRequired,
145                                 requestClientCertificate);
146
147                         this.protocol = new ServerRecordProtocol(innerStream, (ServerContext)this.context);
148                 }
149
150                 #endregion
151
152                 #region Finalizer
153
154                 ~SslServerStream()
155                 {
156                         this.Dispose(false);
157                 }
158
159                 #endregion
160
161                 #region IDisposable Methods
162
163                 protected override void Dispose(bool disposing)
164                 {
165                         base.Dispose(disposing);
166
167                         if (disposing)
168                         {
169                                 this.ClientCertValidation = null;
170                                 this.PrivateKeySelection = null;
171                         }
172                 }
173
174                 #endregion
175
176                 #region Handsake Methods
177
178                 /*
179                         Client                                                                                  Server
180
181                         ClientHello                 -------->
182                                                                                                                         ServerHello
183                                                                                                                         Certificate*
184                                                                                                                         ServerKeyExchange*
185                                                                                                                         CertificateRequest*
186                                                                                 <--------                       ServerHelloDone
187                         Certificate*
188                         ClientKeyExchange
189                         CertificateVerify*
190                         [ChangeCipherSpec]
191                         Finished                    -------->
192                                                                                                                         [ChangeCipherSpec]
193                                                                                 <--------           Finished
194                         Application Data            <------->                   Application Data
195
196                                         Fig. 1 - Message flow for a full handshake              
197                 */
198
199                 internal override IAsyncResult OnBeginNegotiateHandshake(AsyncCallback callback, object state)
200                 {
201                         // Reset the context if needed
202                         if (this.context.HandshakeState != HandshakeState.None)
203                         {
204                                 this.context.Clear();
205                         }
206
207                         // Obtain supported cipher suites
208                         this.context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers(this.context.SecurityProtocol);
209
210                         // Set handshake state
211                         this.context.HandshakeState = HandshakeState.Started;
212
213                         // Receive Client Hello message
214                         return this.protocol.BeginReceiveRecord(this.innerStream, callback, state);
215
216                 }
217
218                 internal override void OnNegotiateHandshakeCallback(IAsyncResult asyncResult)
219                 {
220                         // Receive Client Hello message and ignore it
221                         this.protocol.EndReceiveRecord(asyncResult);
222
223                         // If received message is not an ClientHello send a
224                         // Fatal Alert
225                         if (this.context.LastHandshakeMsg != HandshakeType.ClientHello)
226                         {
227                                 this.protocol.SendAlert(AlertDescription.UnexpectedMessage);
228                         }
229
230                         // Send ServerHello message
231                         this.protocol.SendRecord(HandshakeType.ServerHello);
232
233                         // Send ServerCertificate message
234                         this.protocol.SendRecord(HandshakeType.Certificate);
235
236                         // If the negotiated cipher is a KeyEx cipher send ServerKeyExchange
237                         if (this.context.Negotiating.Cipher.IsExportable)
238                         {
239                                 this.protocol.SendRecord(HandshakeType.ServerKeyExchange);
240                         }
241
242                         // If the negotiated cipher is a KeyEx cipher or
243                         // the client certificate is required send the CertificateRequest message
244                         if (this.context.Negotiating.Cipher.IsExportable ||
245                                 ((ServerContext)this.context).ClientCertificateRequired ||
246                                 ((ServerContext)this.context).RequestClientCertificate)
247                         {
248                                 this.protocol.SendRecord(HandshakeType.CertificateRequest);
249                         }
250
251                         // Send ServerHelloDone message
252                         this.protocol.SendRecord(HandshakeType.ServerHelloDone);
253
254                         // Receive client response, until the Client Finished message
255                         // is received. IE can be interrupted at this stage and never
256                         // complete the handshake
257                         while (this.context.LastHandshakeMsg != HandshakeType.Finished)
258                         {
259                                 byte[] record = this.protocol.ReceiveRecord(this.innerStream);
260                                 if ((record == null) || (record.Length == 0))
261                                 {
262                                         throw new TlsException(
263                                                 AlertDescription.HandshakeFailiure,
264                                                 "The client stopped the handshake.");
265                                 }
266                         }
267
268                         // Send ChangeCipherSpec and ServerFinished messages
269                         this.protocol.SendChangeCipherSpec();
270                         this.protocol.SendRecord (HandshakeType.Finished);
271
272                         // The handshake is finished
273                         this.context.HandshakeState = HandshakeState.Finished;
274
275                         // Reset Handshake messages information
276                         this.context.HandshakeMessages.Reset ();
277
278                         // Clear Key Info
279                         this.context.ClearKeyInfo();
280                 }
281
282                 #endregion
283
284                 #region Event Methods
285
286                 internal override X509Certificate OnLocalCertificateSelection(X509CertificateCollection clientCertificates, X509Certificate serverCertificate, string targetHost, X509CertificateCollection serverRequestedCertificates)
287                 {
288                         throw new NotSupportedException();
289                 }
290
291                 internal override bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors)
292                 {
293                         if (this.ClientCertValidation != null)
294                         {
295                                 return this.ClientCertValidation(certificate, errors);
296                         }
297
298                         return (errors != null && errors.Length == 0);
299                 }
300
301                 internal override bool HaveRemoteValidation2Callback {
302                         get { return ClientCertValidation2 != null; }
303                 }
304
305                 internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
306                 {
307                         CertificateValidationCallback2 cb = ClientCertValidation2;
308                         if (cb != null)
309                                 return cb (collection);
310                         return null;
311                 }
312
313                 internal bool RaiseClientCertificateValidation(
314                         X509Certificate certificate, 
315                         int[]                   certificateErrors)
316                 {
317                         return base.RaiseRemoteCertificateValidation(certificate, certificateErrors);
318                 }
319
320                 internal override AsymmetricAlgorithm OnLocalPrivateKeySelection(X509Certificate certificate, string targetHost)
321                 {
322                         if (this.PrivateKeySelection != null)
323                         {
324                                 return this.PrivateKeySelection(certificate, targetHost);
325                         }
326
327                         return null;
328                 }
329
330                 internal AsymmetricAlgorithm RaisePrivateKeySelection(
331                         X509Certificate certificate,
332                         string targetHost)
333                 {
334                         return base.RaiseLocalPrivateKeySelection(certificate, targetHost);
335                 }
336
337                 #endregion
338         }
339 }