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