Merge pull request #2250 from esdrubal/master
[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 !MONO_FEATURE_NEW_TLS
28 #if SECURITY_DEP
29
30 #if MONO_SECURITY_ALIAS
31 extern alias MonoSecurity;
32 #endif
33
34 #if MONO_SECURITY_ALIAS
35 using MonoSecurity::Mono.Security.Interface;
36 #else
37 using Mono.Security.Interface;
38 #endif
39
40 using CipherAlgorithmType = System.Security.Authentication.CipherAlgorithmType;
41 using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
42 using ExchangeAlgorithmType = System.Security.Authentication.ExchangeAlgorithmType;
43
44 using System;
45 using System.IO;
46 using System.Net;
47 using System.Net.Security;
48 using System.Security.Authentication;
49 using System.Security.Cryptography.X509Certificates;
50 using System.Security.Permissions;
51 using System.Security.Principal;
52 using System.Security.Cryptography;
53
54 using System.Threading.Tasks;
55
56 using MNS = Mono.Net.Security;
57
58 namespace System.Net.Security
59 {
60         /*
61          * These two are defined by the referencesource; add them heere to make
62          * it easy to switch between the two implementations.
63          */
64
65         internal delegate bool RemoteCertValidationCallback (
66                 string host,
67                 X509Certificate certificate,
68                 X509Chain chain,
69                 SslPolicyErrors sslPolicyErrors);
70
71         internal delegate X509Certificate LocalCertSelectionCallback (
72                 string targetHost,
73                 X509CertificateCollection localCertificates,
74                 X509Certificate remoteCertificate,
75                 string[] acceptableIssuers);
76
77         public class SslStream : AuthenticatedStream, MNS.IMonoSslStream
78         {
79                 MonoTlsProvider provider;
80                 IMonoSslStream impl;
81
82                 internal IMonoSslStream Impl {
83                         get {
84                                 CheckDisposed ();
85                                 return impl;
86                         }
87                 }
88
89                 internal MonoTlsProvider Provider {
90                         get {
91                                 CheckDisposed ();
92                                 return provider;
93                         }
94                 }
95
96                 static MonoTlsProvider GetProvider ()
97                 {
98                         return MonoTlsProviderFactory.GetDefaultProvider ();
99                 }
100
101                 public SslStream (Stream innerStream)
102                         : this (innerStream, false)
103                 {
104                 }
105
106                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen)
107                         : base (innerStream, leaveInnerStreamOpen)
108                 {
109                         provider = GetProvider ();
110                         impl = provider.CreateSslStream (innerStream, leaveInnerStreamOpen);
111                 }
112
113                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback)
114                         : this (innerStream, leaveInnerStreamOpen, userCertificateValidationCallback, null)
115                 {
116                 }
117
118                 public SslStream (Stream innerStream, bool leaveInnerStreamOpen, RemoteCertificateValidationCallback userCertificateValidationCallback, LocalCertificateSelectionCallback userCertificateSelectionCallback)
119                         : base (innerStream, leaveInnerStreamOpen)
120                 {
121                         provider = GetProvider ();
122                         var settings = MonoTlsSettings.CopyDefaultSettings ();
123                         settings.RemoteCertificateValidationCallback = MNS.Private.CallbackHelpers.PublicToMono (userCertificateValidationCallback);
124                         settings.ClientCertificateSelectionCallback = MNS.Private.CallbackHelpers.PublicToMono (userCertificateSelectionCallback);
125                         impl = provider.CreateSslStream (innerStream, leaveInnerStreamOpen, settings);
126                 }
127
128                 internal SslStream (Stream innerStream, bool leaveInnerStreamOpen, IMonoSslStream impl)
129                         : base (innerStream, leaveInnerStreamOpen)
130                 {
131                         this.impl = impl;
132                 }
133
134                 public virtual void AuthenticateAsClient (string targetHost)
135                 {
136                         Impl.AuthenticateAsClient (targetHost);
137                 }
138
139                 public virtual void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
140                 {
141                         Impl.AuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation);
142                 }
143
144                 // [HostProtection (ExternalThreading=true)]
145                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
146                 {
147                         return Impl.BeginAuthenticateAsClient (targetHost, asyncCallback, asyncState);
148                 }
149
150                 // [HostProtection (ExternalThreading=true)]
151                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
152                 {
153                         return Impl.BeginAuthenticateAsClient (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState);
154                 }
155
156                 public virtual void EndAuthenticateAsClient (IAsyncResult asyncResult)
157                 {
158                         Impl.EndAuthenticateAsClient (asyncResult);
159                 }
160
161                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate)
162                 {
163                         Impl.AuthenticateAsServer (serverCertificate);
164                 }
165
166                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
167                 {
168                         Impl.AuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation);
169                 }
170
171                 // [HostProtection (ExternalThreading=true)]
172                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState)
173                 {
174                         return Impl.BeginAuthenticateAsServer (serverCertificate, asyncCallback, asyncState);
175                 }
176
177                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
178                 {
179                         return Impl.BeginAuthenticateAsServer (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, asyncCallback, asyncState);
180                 }
181
182                 public virtual void EndAuthenticateAsServer (IAsyncResult asyncResult)
183                 {
184                         Impl.EndAuthenticateAsServer (asyncResult);
185                 }
186
187                 public TransportContext TransportContext {
188                         get {
189                                 throw new NotSupportedException();
190                         }
191                 }
192
193                 // [HostProtection (ExternalThreading=true)]
194                 public virtual Task AuthenticateAsClientAsync (string targetHost)
195                 {
196                         return Impl.AuthenticateAsClientAsync (targetHost);
197                 }
198
199                 public virtual Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
200                 {
201                         return Impl.AuthenticateAsClientAsync (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation);
202                 }
203
204                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate)
205                 {
206                         return Impl.AuthenticateAsServerAsync (serverCertificate);
207                 }
208
209                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
210                 {
211                         return Impl.AuthenticateAsServerAsync (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation);
212                 }
213
214                 public override bool IsAuthenticated {
215                         get { return Impl.IsAuthenticated; }
216                 }
217
218                 public override bool IsMutuallyAuthenticated {
219                         get { return Impl.IsMutuallyAuthenticated; }
220                 }
221
222                 public override bool IsEncrypted {
223                         get { return Impl.IsEncrypted; }
224                 }
225
226                 public override bool IsSigned {
227                         get { return Impl.IsSigned; }
228                 }
229
230                 public override bool IsServer {
231                         get { return Impl.IsServer; }
232                 }
233
234                 public virtual SslProtocols SslProtocol {
235                         get { return (SslProtocols)Impl.SslProtocol; }
236                 }
237
238                 public virtual bool CheckCertRevocationStatus {
239                         get { return Impl.CheckCertRevocationStatus; }
240                 }
241
242                 X509Certificate MNS.IMonoSslStream.InternalLocalCertificate {
243                         get { return Impl.InternalLocalCertificate; }
244                 }
245
246                 public virtual X509Certificate LocalCertificate {
247                         get { return Impl.LocalCertificate; }
248                 }
249
250                 public virtual X509Certificate RemoteCertificate {
251                         get { return Impl.RemoteCertificate; }
252                 }
253
254                 public virtual CipherAlgorithmType CipherAlgorithm {
255                         get { return (CipherAlgorithmType)Impl.CipherAlgorithm; }
256                 }
257
258                 public virtual int CipherStrength {
259                         get { return Impl.CipherStrength; }
260                 }
261
262                 public virtual HashAlgorithmType HashAlgorithm {
263                         get { return (HashAlgorithmType)Impl.HashAlgorithm; }
264                 }
265
266                 public virtual int HashStrength {
267                         get { return Impl.HashStrength; }
268                 }
269
270                 public virtual ExchangeAlgorithmType KeyExchangeAlgorithm {
271                         get { return (ExchangeAlgorithmType)Impl.KeyExchangeAlgorithm; }
272                 }
273
274                 public virtual int KeyExchangeStrength {
275                         get { return Impl.KeyExchangeStrength; }
276                 }
277
278                 public override bool CanSeek {
279                         get { return false; }
280                 }
281
282                 public override bool CanRead {
283                         get { return Impl.CanRead; }
284                 }
285
286                 public override bool CanTimeout {
287                         get { return Impl.CanTimeout; }
288                 }
289
290                 public override bool CanWrite {
291                         get { return Impl.CanWrite; }
292                 }
293
294                 public override int ReadTimeout {
295                         get { return Impl.ReadTimeout; }
296                         set { Impl.ReadTimeout = value; }
297                 }
298
299                 public override int WriteTimeout {
300                         get { return Impl.WriteTimeout; }
301                         set { Impl.WriteTimeout = value; }
302                 }
303
304                 public override long Length {
305                         get { return Impl.Length; }
306                 }
307
308                 public override long Position {
309                         get { return Impl.Position; }
310                         set {
311                                 throw new NotSupportedException (SR.GetString (SR.net_noseek));
312                         }
313                 }
314
315                 public override void SetLength (long value)
316                 {
317                         Impl.SetLength (value);
318                 }
319
320                 public override long Seek (long offset, SeekOrigin origin)
321                 {
322                         throw new NotSupportedException (SR.GetString (SR.net_noseek));
323                 }
324
325                 public override void Flush ()
326                 {
327                         Impl.Flush ();
328                 }
329
330                 void CheckDisposed ()
331                 {
332                         if (impl == null)
333                                 throw new ObjectDisposedException ("SslStream");
334                 }
335
336                 protected override void Dispose (bool disposing)
337                 {
338                         try {
339                                 if (impl != null && disposing) {
340                                         impl.Dispose ();
341                                         impl = null;
342                                 }
343                         } finally {
344                                 base.Dispose (disposing);
345                         }
346                 }
347
348                 public override int Read (byte[] buffer, int offset, int count)
349                 {
350                         return Impl.Read (buffer, offset, count);
351                 }
352
353                 public void Write (byte[] buffer)
354                 {
355                         Impl.Write (buffer);
356                 }
357
358                 public override void Write (byte[] buffer, int offset, int count)
359                 {
360                         Impl.Write (buffer, offset, count);
361                 }
362
363                 // [HostProtection (ExternalThreading=true)]
364                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
365                 {
366                         return Impl.BeginRead (buffer, offset, count, asyncCallback, asyncState);
367                 }
368
369                 public override int EndRead (IAsyncResult asyncResult)
370                 {
371                         return Impl.EndRead (asyncResult);
372                 }
373
374                 // [HostProtection (ExternalThreading=true)]
375                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
376                 {
377                         return Impl.BeginWrite (buffer, offset, count, asyncCallback, asyncState);
378                 }
379
380                 public override void EndWrite (IAsyncResult asyncResult)
381                 {
382                         Impl.EndWrite (asyncResult);
383                 }
384
385                 AuthenticatedStream MNS.IMonoSslStream.AuthenticatedStream {
386                         get { return this; }
387                 }
388
389                 MonoTlsProvider MNS.IMonoSslStream.Provider {
390                         get { return provider; }
391                 }
392
393                 MonoTlsConnectionInfo MNS.IMonoSslStream.GetConnectionInfo ()
394                 {
395                         return Impl.GetConnectionInfo ();
396                 }
397         }
398 }
399 #else // !SECURITY_DEP
400 namespace System.Net.Security
401 {
402         public class SslStream
403         {
404         }
405 }
406 #endif
407
408 #endif