[HttpConnection] Bug fix: HttpListener's "IgnoreWriteExceptions" property value is...
[mono.git] / mcs / class / System / System.Net.Security / SslStream.cs
1 //
2 // SslStream.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2015 Xamarin, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26
27 #if SECURITY_DEP && !MONO_FEATURE_NEW_TLS
28
29 #if MONO_X509_ALIAS
30 extern alias PrebuiltSystem;
31 #endif
32 #if MONO_SECURITY_ALIAS
33 extern alias MonoSecurity;
34 #endif
35
36 #if MONO_SECURITY_ALIAS
37 using MonoSecurity::Mono.Security.Interface;
38 #else
39 using Mono.Security.Interface;
40 #endif
41 #if MONO_X509_ALIAS
42 using XSslProtocols = PrebuiltSystem::System.Security.Authentication.SslProtocols;
43 using XX509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
44 #else
45 using XSslProtocols = System.Security.Authentication.SslProtocols;
46 using XX509CertificateCollection = System.Security.Cryptography.X509Certificates.X509CertificateCollection;
47 #endif
48
49 using CipherAlgorithmType = System.Security.Authentication.CipherAlgorithmType;
50 using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
51 using ExchangeAlgorithmType = System.Security.Authentication.ExchangeAlgorithmType;
52
53 using System;
54 using System.IO;
55 using System.Net;
56 using System.Net.Security;
57 using System.Security.Authentication;
58 using System.Security.Cryptography.X509Certificates;
59 using System.Security.Permissions;
60 using System.Security.Principal;
61 using System.Security.Cryptography;
62
63 using System.Threading.Tasks;
64
65 using MNS = Mono.Net.Security;
66
67 namespace System.Net.Security
68 {
69         /*
70          * These two are defined by the referencesource; add them heere to make
71          * it easy to switch between the two implementations.
72          */
73
74         internal delegate bool RemoteCertValidationCallback (
75                 string host,
76                 X509Certificate certificate,
77                 X509Chain chain,
78                 SslPolicyErrors sslPolicyErrors);
79
80         internal delegate X509Certificate LocalCertSelectionCallback (
81                 string targetHost,
82                 XX509CertificateCollection localCertificates,
83                 X509Certificate remoteCertificate,
84                 string[] acceptableIssuers);
85
86         public class SslStream : AuthenticatedStream, MNS.IMonoSslStream
87         {
88                 MonoSslStream impl;
89
90                 internal MonoSslStream Impl {
91                         get {
92                                 CheckDisposed ();
93                                 return impl;
94                         }
95                 }
96
97                 static MonoTlsProvider GetProvider ()
98                 {
99                         return MonoTlsProviderFactory.GetDefaultProvider ();
100                 }
101
102                 public SslStream (Stream innerStream)
103                         : this (innerStream, false)
104                 {
105                 }
106
107                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen)
108                         : base (innerStream, leaveInnerStreamOpen)
109                 {
110                         var provider = GetProvider ();
111                         impl = provider.CreateSslStream (innerStream, leaveInnerStreamOpen);
112                 }
113
114                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback)
115                         : this (innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, null)
116                 {
117                 }
118
119                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback)
120                         : base (innerStream, leaveInnerStreamOpen)
121                 {
122                         var provider = GetProvider ();
123                         var settings = new MonoTlsSettings ();
124                         settings.RemoteCertificateValidationCallback = MNS.Private.CallbackHelpers.PublicToMono (userCertificateValidationCallback);
125                         settings.ClientCertificateSelectionCallback = MNS.Private.CallbackHelpers.PublicToMono (userCertificateSelectionCallback);
126                         impl = provider.CreateSslStream (innerStream, leaveInnerStreamOpen, settings);
127                 }
128
129                 internal SslStream (Stream innerStream, bool leaveInnerStreamOpen, MonoSslStream impl)
130                         : base (innerStream, leaveInnerStreamOpen)
131                 {
132                         this.impl = impl;
133                 }
134
135                 public virtual void AuthenticateAsClient (string targetHost)
136                 {
137                         Impl.AuthenticateAsClient (targetHost);
138                 }
139
140                 public virtual void AuthenticateAsClient (string targetHost, XX509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
141                 {
142                         Impl.AuthenticateAsClient (targetHost, (XX509CertificateCollection)(object)clientCertificates, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation);
143                 }
144
145                 // [HostProtection (ExternalThreading=true)]
146                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
147                 {
148                         return Impl.BeginAuthenticateAsClient (targetHost, asyncCallback, asyncState);
149                 }
150
151                 // [HostProtection (ExternalThreading=true)]
152                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, XX509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
153                 {
154                         return Impl.BeginAuthenticateAsClient (targetHost, (XX509CertificateCollection)(object)clientCertificates, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState);
155                 }
156
157                 public virtual void EndAuthenticateAsClient (IAsyncResult asyncResult)
158                 {
159                         Impl.EndAuthenticateAsClient (asyncResult);
160                 }
161
162                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate)
163                 {
164                         Impl.AuthenticateAsServer (serverCertificate);
165                 }
166
167                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
168                 {
169                         Impl.AuthenticateAsServer (serverCertificate, clientCertificateRequired, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation);
170                 }
171
172                 // [HostProtection (ExternalThreading=true)]
173                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState)
174                 {
175                         return Impl.BeginAuthenticateAsServer (serverCertificate, asyncCallback, asyncState);
176                 }
177
178                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
179                 {
180                         return Impl.BeginAuthenticateAsServer (serverCertificate, clientCertificateRequired, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState);
181                 }
182
183                 public virtual void EndAuthenticateAsServer (IAsyncResult asyncResult)
184                 {
185                         Impl.EndAuthenticateAsServer (asyncResult);
186                 }
187
188                 public TransportContext TransportContext {
189                         get {
190                                 throw new NotSupportedException();
191                         }
192                 }
193
194                 // [HostProtection (ExternalThreading=true)]
195                 public virtual Task AuthenticateAsClientAsync (string targetHost)
196                 {
197                         return Impl.AuthenticateAsClientAsync (targetHost);
198                 }
199
200                 public virtual Task AuthenticateAsClientAsync (string targetHost, XX509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
201                 {
202                         return Impl.AuthenticateAsClientAsync (targetHost, clientCertificates, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation);
203                 }
204
205                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate)
206                 {
207                         return Impl.AuthenticateAsServerAsync (serverCertificate);
208                 }
209
210                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
211                 {
212                         return Impl.AuthenticateAsServerAsync (serverCertificate, clientCertificateRequired, (XSslProtocols)enabledSslProtocols, checkCertificateRevocation);
213                 }
214
215                 public override bool IsAuthenticated {
216                         get { return Impl.IsAuthenticated; }
217                 }
218
219                 public override bool IsMutuallyAuthenticated {
220                         get { return Impl.IsMutuallyAuthenticated; }
221                 }
222
223                 public override bool IsEncrypted {
224                         get { return Impl.IsEncrypted; }
225                 }
226
227                 public override bool IsSigned {
228                         get { return Impl.IsSigned; }
229                 }
230
231                 public override bool IsServer {
232                         get { return Impl.IsServer; }
233                 }
234
235                 public virtual SslProtocols SslProtocol {
236                         get { return (SslProtocols)Impl.SslProtocol; }
237                 }
238
239                 public virtual bool CheckCertRevocationStatus {
240                         get { return Impl.CheckCertRevocationStatus; }
241                 }
242
243                 X509Certificate MNS.IMonoSslStream.InternalLocalCertificate {
244                         get { return Impl.InternalLocalCertificate; }
245                 }
246
247                 public virtual X509Certificate LocalCertificate {
248                         get { return Impl.LocalCertificate; }
249                 }
250
251                 public virtual X509Certificate RemoteCertificate {
252                         get { return Impl.RemoteCertificate; }
253                 }
254
255                 public virtual CipherAlgorithmType CipherAlgorithm {
256                         get { return (CipherAlgorithmType)Impl.CipherAlgorithm; }
257                 }
258
259                 public virtual int CipherStrength {
260                         get { return Impl.CipherStrength; }
261                 }
262
263                 public virtual HashAlgorithmType HashAlgorithm {
264                         get { return (HashAlgorithmType)Impl.HashAlgorithm; }
265                 }
266
267                 public virtual int HashStrength {
268                         get { return Impl.HashStrength; }
269                 }
270
271                 public virtual ExchangeAlgorithmType KeyExchangeAlgorithm {
272                         get { return (ExchangeAlgorithmType)Impl.KeyExchangeAlgorithm; }
273                 }
274
275                 public virtual int KeyExchangeStrength {
276                         get { return Impl.KeyExchangeStrength; }
277                 }
278
279                 public override bool CanSeek {
280                         get { return false; }
281                 }
282
283                 public override bool CanRead {
284                         get { return Impl.CanRead; }
285                 }
286
287                 public override bool CanTimeout {
288                         get { return Impl.CanTimeout; }
289                 }
290
291                 public override bool CanWrite {
292                         get { return Impl.CanWrite; }
293                 }
294
295                 public override int ReadTimeout {
296                         get { return Impl.ReadTimeout; }
297                         set { Impl.ReadTimeout = value; }
298                 }
299
300                 public override int WriteTimeout {
301                         get { return Impl.WriteTimeout; }
302                         set { Impl.WriteTimeout = value; }
303                 }
304
305                 public override long Length {
306                         get { return Impl.Length; }
307                 }
308
309                 public override long Position {
310                         get { return Impl.Position; }
311                         set {
312                                 throw new NotSupportedException (SR.GetString (SR.net_noseek));
313                         }
314                 }
315
316                 public override void SetLength (long value)
317                 {
318                         Impl.SetLength (value);
319                 }
320
321                 public override long Seek (long offset, SeekOrigin origin)
322                 {
323                         throw new NotSupportedException (SR.GetString (SR.net_noseek));
324                 }
325
326                 public override void Flush ()
327                 {
328                         Impl.Flush ();
329                 }
330
331                 void CheckDisposed ()
332                 {
333                         if (impl == null)
334                                 throw new ObjectDisposedException ("MonoSslStream");
335                 }
336
337                 protected override void Dispose (bool disposing)
338                 {
339                         try {
340                                 if (impl != null && disposing) {
341                                         impl.Dispose ();
342                                         impl = null;
343                                 }
344                         } finally {
345                                 base.Dispose (disposing);
346                         }
347                 }
348
349                 public override int Read (byte[] buffer, int offset, int count)
350                 {
351                         return Impl.Read (buffer, offset, count);
352                 }
353
354                 public void Write (byte[] buffer)
355                 {
356                         Impl.Write (buffer);
357                 }
358
359                 public override void Write (byte[] buffer, int offset, int count)
360                 {
361                         Impl.Write (buffer, offset, count);
362                 }
363
364                 // [HostProtection (ExternalThreading=true)]
365                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
366                 {
367                         return Impl.BeginRead (buffer, offset, count, asyncCallback, asyncState);
368                 }
369
370                 public override int EndRead (IAsyncResult asyncResult)
371                 {
372                         return Impl.EndRead (asyncResult);
373                 }
374
375                 // [HostProtection (ExternalThreading=true)]
376                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
377                 {
378                         return Impl.BeginWrite (buffer, offset, count, asyncCallback, asyncState);
379                 }
380
381                 public override void EndWrite (IAsyncResult asyncResult)
382                 {
383                         Impl.EndWrite (asyncResult);
384                 }
385
386                 AuthenticatedStream MNS.IMonoSslStream.AuthenticatedStream {
387                         get { return this; }
388                 }
389         }
390 }
391
392 #endif