[Mono.Security]: Add 'IMonoSslStream.Provider' and 'GetConnectionInfo()'.
[mono.git] / mcs / class / System / Mono.Net.Security / LegacySslStream.cs
1 //
2 // System.Net.Security.SslStream.cs
3 //
4 // Authors:
5 //      Tim Coleman (tim@timcoleman.com)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 //      Marek Safar (marek.safar@gmail.com)
8 //
9 // Copyright (C) Tim Coleman, 2004
10 // (c) 2004,2007 Novell, Inc. (http://www.novell.com)
11 // Copyright 2011 Xamarin Inc.
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 #if SECURITY_DEP
36
37 #if MONO_X509_ALIAS
38 extern alias PrebuiltSystem;
39 #endif
40 #if MONO_SECURITY_ALIAS
41 extern alias MonoSecurity;
42 #endif
43
44 #if MONO_SECURITY_ALIAS
45 using MonoCipherAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.CipherAlgorithmType;
46 using MonoHashAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.HashAlgorithmType;
47 using MonoExchangeAlgorithmType = MonoSecurity::Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
48 using MonoSecurityProtocolType = MonoSecurity::Mono.Security.Protocol.Tls.SecurityProtocolType;
49 using MonoSecurity::Mono.Security.Protocol.Tls;
50 using MonoSecurity::Mono.Security.Interface;
51 #else
52 using MonoCipherAlgorithmType = Mono.Security.Protocol.Tls.CipherAlgorithmType;
53 using MonoHashAlgorithmType = Mono.Security.Protocol.Tls.HashAlgorithmType;
54 using MonoExchangeAlgorithmType = Mono.Security.Protocol.Tls.ExchangeAlgorithmType;
55 using MonoSecurityProtocolType = Mono.Security.Protocol.Tls.SecurityProtocolType;
56 using Mono.Security.Protocol.Tls;
57 using Mono.Security.Interface;
58 #endif
59 #if MONO_X509_ALIAS
60 using X509CertificateCollection = PrebuiltSystem::System.Security.Cryptography.X509Certificates.X509CertificateCollection;
61 #endif
62
63 using CipherAlgorithmType = System.Security.Authentication.CipherAlgorithmType;
64 using HashAlgorithmType = System.Security.Authentication.HashAlgorithmType;
65 using ExchangeAlgorithmType = System.Security.Authentication.ExchangeAlgorithmType;
66
67 using System;
68 using System.IO;
69 using System.Net;
70 using System.Net.Security;
71 using System.Security.Authentication;
72 using System.Security.Cryptography.X509Certificates;
73 using System.Security.Principal;
74 using System.Security.Cryptography;
75
76 using System.Threading.Tasks;
77
78 namespace Mono.Net.Security.Private
79 {
80         /*
81          * Strictly private - do not use outside the Mono.Net.Security directory.
82          */
83         [MonoTODO ("Non-X509Certificate2 certificate is not supported")]
84         internal class LegacySslStream : AuthenticatedStream, IMonoSslStream
85         {
86                 #region Fields
87
88                 SslStreamBase ssl_stream;
89                 ICertificateValidator certificateValidator;
90                 MonoTlsProvider provider;
91
92                 #endregion // Fields
93
94                 #region Constructors
95
96                 public LegacySslStream (Stream innerStream, bool leaveInnerStreamOpen, MonoTlsProvider provider, MonoTlsSettings settings)
97                         : base (innerStream, leaveInnerStreamOpen)
98                 {
99                         this.provider = provider;
100                         certificateValidator = ChainValidationHelper.GetDefaultValidator (provider, settings);
101                 }
102                 #endregion // Constructors
103
104                 #region Properties
105
106                 public override bool CanRead {
107                         get { return InnerStream.CanRead; }
108                 }
109
110                 public override bool CanSeek {
111                         get { return InnerStream.CanSeek; }
112                 }
113
114                 public override bool CanTimeout {
115                         get { return InnerStream.CanTimeout; }
116                 }
117
118                 public override bool CanWrite {
119                         get { return InnerStream.CanWrite; }
120                 }
121
122                 public override long Length {
123                         get { return InnerStream.Length; }
124                 }
125
126                 public override long Position {
127                         get { return InnerStream.Position; }
128                         set {
129                                 throw new NotSupportedException ("This stream does not support seek operations");
130                         }
131                 }
132
133                 // AuthenticatedStream overrides
134
135                 public override bool IsAuthenticated { 
136                         get { return ssl_stream != null; }
137                 }
138
139                 public override bool IsEncrypted { 
140                         get { return IsAuthenticated; }
141                 }
142
143                 public override bool IsMutuallyAuthenticated { 
144                         get { return IsAuthenticated && (IsServer ? RemoteCertificate != null : LocalCertificate != null); }
145                 }
146
147                 public override bool IsServer { 
148                         get { return ssl_stream is SslServerStream; }
149                 }
150
151                 public override bool IsSigned { 
152                         get { return IsAuthenticated; }
153                 }
154
155                 public override int ReadTimeout {
156                         get { return InnerStream.ReadTimeout; }
157                         set { InnerStream.ReadTimeout = value; }
158                 }
159
160                 public override int WriteTimeout {
161                         get { return InnerStream.WriteTimeout; }
162                         set { InnerStream.WriteTimeout = value; }
163                 }
164
165                 // SslStream
166
167                 public virtual bool CheckCertRevocationStatus {
168                         get {
169                                 if (!IsAuthenticated)
170                                         return false;
171
172                                 return ssl_stream.CheckCertRevocationStatus;
173                         }
174                 }
175
176                 public virtual CipherAlgorithmType CipherAlgorithm  {
177                         get {
178                                 CheckConnectionAuthenticated ();
179
180                                 switch (ssl_stream.CipherAlgorithm) {
181                                 case MonoCipherAlgorithmType.Des:
182                                         return CipherAlgorithmType.Des;
183                                 case MonoCipherAlgorithmType.None:
184                                         return CipherAlgorithmType.None;
185                                 case MonoCipherAlgorithmType.Rc2:
186                                         return CipherAlgorithmType.Rc2;
187                                 case MonoCipherAlgorithmType.Rc4:
188                                         return CipherAlgorithmType.Rc4;
189                                 case MonoCipherAlgorithmType.SkipJack:
190                                         break;
191                                 case MonoCipherAlgorithmType.TripleDes:
192                                         return CipherAlgorithmType.TripleDes;
193                                 case MonoCipherAlgorithmType.Rijndael:
194                                         switch (ssl_stream.CipherStrength) {
195                                         case 128:
196                                                 return CipherAlgorithmType.Aes128;
197                                         case 192:
198                                                 return CipherAlgorithmType.Aes192;
199                                         case 256:
200                                                 return CipherAlgorithmType.Aes256;
201                                         }
202                                         break;
203                                 }
204
205                                 throw new InvalidOperationException ("Not supported cipher algorithm is in use. It is likely a bug in SslStream.");
206                         }
207                 }
208
209                 public virtual int CipherStrength  {
210                         get {
211                                 CheckConnectionAuthenticated ();
212
213                                 return ssl_stream.CipherStrength;
214                         }
215                 }
216
217                 public virtual HashAlgorithmType HashAlgorithm  {
218                         get {
219                                 CheckConnectionAuthenticated ();
220
221                                 switch (ssl_stream.HashAlgorithm) {
222                                 case MonoHashAlgorithmType.Md5:
223                                         return HashAlgorithmType.Md5;
224                                 case MonoHashAlgorithmType.None:
225                                         return HashAlgorithmType.None;
226                                 case MonoHashAlgorithmType.Sha1:
227                                         return HashAlgorithmType.Sha1;
228                                 }
229
230                                 throw new InvalidOperationException ("Not supported hash algorithm is in use. It is likely a bug in SslStream.");
231                         }
232                 }
233
234                 public virtual int HashStrength  {
235                         get {
236                                 CheckConnectionAuthenticated ();
237
238                                 return ssl_stream.HashStrength;
239                         }
240                 }
241
242                 public virtual ExchangeAlgorithmType KeyExchangeAlgorithm { 
243                         get {
244                                 CheckConnectionAuthenticated ();
245
246                                 switch (ssl_stream.KeyExchangeAlgorithm) {
247                                 case MonoExchangeAlgorithmType.DiffieHellman:
248                                         return ExchangeAlgorithmType.DiffieHellman;
249                                 case MonoExchangeAlgorithmType.Fortezza:
250                                         break;
251                                 case MonoExchangeAlgorithmType.None:
252                                         return ExchangeAlgorithmType.None;
253                                 case MonoExchangeAlgorithmType.RsaKeyX:
254                                         return ExchangeAlgorithmType.RsaKeyX;
255                                 case MonoExchangeAlgorithmType.RsaSign:
256                                         return ExchangeAlgorithmType.RsaSign;
257                                 }
258
259                                 throw new InvalidOperationException ("Not supported exchange algorithm is in use. It is likely a bug in SslStream.");
260                         }
261                 }
262
263                 public virtual int KeyExchangeStrength { 
264                         get {
265                                 CheckConnectionAuthenticated ();
266
267                                 return ssl_stream.KeyExchangeStrength;
268                         }
269                 }
270
271                 X509Certificate IMonoSslStream.InternalLocalCertificate {
272                         get {
273                                 return IsServer ? ssl_stream.ServerCertificate : ((SslClientStream) ssl_stream).SelectedClientCertificate;
274                         }
275                 }
276
277                 public virtual X509Certificate LocalCertificate {
278                         get {
279                                 CheckConnectionAuthenticated ();
280
281                                 return IsServer ? ssl_stream.ServerCertificate : ((SslClientStream) ssl_stream).SelectedClientCertificate;
282                         }
283                 }
284
285                 public virtual X509Certificate RemoteCertificate {
286                         get {
287                                 CheckConnectionAuthenticated ();
288                                 return !IsServer ? ssl_stream.ServerCertificate : ((SslServerStream) ssl_stream).ClientCertificate;
289                         }
290                 }
291
292                 public virtual SslProtocols SslProtocol {
293                         get {
294                                 CheckConnectionAuthenticated ();
295
296                                 switch (ssl_stream.SecurityProtocol) {
297                                 case MonoSecurityProtocolType.Default:
298                                         return SslProtocols.Default;
299                                 case MonoSecurityProtocolType.Ssl2:
300                                         return SslProtocols.Ssl2;
301                                 case MonoSecurityProtocolType.Ssl3:
302                                         return SslProtocols.Ssl3;
303                                 case MonoSecurityProtocolType.Tls:
304                                         return SslProtocols.Tls;
305                                 }
306
307                                 throw new InvalidOperationException ("Not supported SSL/TLS protocol is in use. It is likely a bug in SslStream.");
308                         }
309                 }
310
311                 #endregion // Properties
312
313                 #region Methods
314
315 /*
316                 AsymmetricAlgorithm GetPrivateKey (X509Certificate cert, string targetHost)
317                 {
318                         // FIXME: what can I do for non-X509Certificate2 ?
319                         X509Certificate2 cert2 = cert as X509Certificate2;
320                         return cert2 != null ? cert2.PrivateKey : null;
321                 }
322 */
323                 X509Certificate OnCertificateSelection (X509CertificateCollection clientCerts, X509Certificate serverCert, string targetHost, X509CertificateCollection serverRequestedCerts)
324                 {
325                         string [] acceptableIssuers = new string [serverRequestedCerts != null ? serverRequestedCerts.Count : 0];
326                         for (int i = 0; i < acceptableIssuers.Length; i++)
327                                 acceptableIssuers [i] = serverRequestedCerts [i].GetIssuerName ();
328                         X509Certificate clientCertificate;
329                         certificateValidator.SelectClientCertificate (targetHost, clientCerts, serverCert, acceptableIssuers, out clientCertificate);
330                         return clientCertificate;
331                 }
332
333                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, AsyncCallback asyncCallback, object asyncState)
334                 {
335                         return BeginAuthenticateAsClient (targetHost, new X509CertificateCollection (), SslProtocols.Tls, false, asyncCallback, asyncState);
336                 }
337
338                 public virtual IAsyncResult BeginAuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
339                 {
340                         if (IsAuthenticated)
341                                 throw new InvalidOperationException ("This SslStream is already authenticated");
342
343                         SslClientStream s = new SslClientStream (InnerStream, targetHost, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols), clientCertificates);
344                         s.CheckCertRevocationStatus = checkCertificateRevocation;
345
346                         // Due to the Mono.Security internal, it cannot reuse
347                         // the delegated argument, as Mono.Security creates 
348                         // another instance of X509Certificate which lacks 
349                         // private key but is filled the private key via this
350                         // delegate.
351                         s.PrivateKeyCertSelectionDelegate = delegate (X509Certificate cert, string host) {
352                                 string hash = cert.GetCertHashString ();
353                                 // ... so, we cannot use the delegate argument.
354                                 foreach (X509Certificate cc in clientCertificates) {
355                                         if (cc.GetCertHashString () != hash)
356                                                 continue;
357                                         X509Certificate2 cert2 = cc as X509Certificate2;
358                                         cert2 = cert2 ?? new X509Certificate2 (cc);
359                                         return cert2.PrivateKey;
360                                 }
361                                 return null;
362                         };
363
364                         // Even if validation_callback is null this allows us to verify requests where the user
365                         // does not provide a verification callback but attempts to authenticate with the website
366                         // as a client (see https://bugzilla.xamarin.com/show_bug.cgi?id=18962 for an example)
367                         s.ServerCertValidation2 += (mcerts) => {
368                                 X509CertificateCollection certs = null;
369                                 if (mcerts != null) {
370                                         certs = new X509CertificateCollection ();
371                                         for (int i = 0; i < mcerts.Count; i++)
372                                                 certs.Add (new X509Certificate2 (mcerts [i].RawData));
373                                 }
374                                 return ((ChainValidationHelper)certificateValidator).ValidateCertificate (targetHost, false, certs);
375                         };
376                         s.ClientCertSelectionDelegate = OnCertificateSelection;
377
378                         ssl_stream = s;
379
380                         return BeginWrite (new byte [0], 0, 0, asyncCallback, asyncState);
381                 }
382
383                 public override IAsyncResult BeginRead (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
384                 {
385                         CheckConnectionAuthenticated ();
386
387                         return ssl_stream.BeginRead (buffer, offset, count, asyncCallback, asyncState);
388                 }
389
390                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, AsyncCallback asyncCallback, object asyncState)
391                 {
392                         return BeginAuthenticateAsServer (serverCertificate, false, SslProtocols.Tls, false, asyncCallback, asyncState);
393                 }
394
395                 public virtual IAsyncResult BeginAuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState)
396                 {
397                         if (IsAuthenticated)
398                                 throw new InvalidOperationException ("This SslStream is already authenticated");
399
400                         SslServerStream s = new SslServerStream (InnerStream, serverCertificate, false, clientCertificateRequired, !LeaveInnerStreamOpen, GetMonoSslProtocol (enabledSslProtocols));
401                         s.CheckCertRevocationStatus = checkCertificateRevocation;
402                         // Due to the Mono.Security internal, it cannot reuse
403                         // the delegated argument, as Mono.Security creates 
404                         // another instance of X509Certificate which lacks 
405                         // private key but is filled the private key via this
406                         // delegate.
407                         s.PrivateKeyCertSelectionDelegate = delegate (X509Certificate cert, string targetHost) {
408                                 // ... so, we cannot use the delegate argument.
409                                 X509Certificate2 cert2 = serverCertificate as X509Certificate2 ?? new X509Certificate2 (serverCertificate);
410                                 return cert2 != null ? cert2.PrivateKey : null;
411                         };
412
413                         s.ClientCertValidationDelegate = delegate (X509Certificate cert, int[] certErrors) {
414                                 var errors = certErrors.Length > 0 ? MonoSslPolicyErrors.RemoteCertificateChainErrors : MonoSslPolicyErrors.None;
415                                 return ((ChainValidationHelper)certificateValidator).ValidateClientCertificate (cert, errors);
416                         };
417
418                         ssl_stream = s;
419
420                         return BeginWrite (new byte[0], 0, 0, asyncCallback, asyncState);
421                 }
422
423                 MonoSecurityProtocolType GetMonoSslProtocol (SslProtocols ms)
424                 {
425                         switch (ms) {
426                         case SslProtocols.Ssl2:
427                                 return MonoSecurityProtocolType.Ssl2;
428                         case SslProtocols.Ssl3:
429                                 return MonoSecurityProtocolType.Ssl3;
430                         case SslProtocols.Tls:
431                                 return MonoSecurityProtocolType.Tls;
432                         default:
433                                 return MonoSecurityProtocolType.Default;
434                         }
435                 }
436
437                 public override IAsyncResult BeginWrite (byte[] buffer, int offset, int count, AsyncCallback asyncCallback, object asyncState)
438                 {
439                         CheckConnectionAuthenticated ();
440
441                         return ssl_stream.BeginWrite (buffer, offset, count, asyncCallback, asyncState);
442                 }
443
444                 public virtual void AuthenticateAsClient (string targetHost)
445                 {
446                         AuthenticateAsClient (targetHost, new X509CertificateCollection (), SslProtocols.Tls, false);
447                 }
448
449                 public virtual void AuthenticateAsClient (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
450                 {
451                         EndAuthenticateAsClient (BeginAuthenticateAsClient (
452                                 targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, null, null));
453                 }
454
455                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate)
456                 {
457                         AuthenticateAsServer (serverCertificate, false, SslProtocols.Tls, false);
458                 }
459
460                 public virtual void AuthenticateAsServer (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
461                 {
462                         EndAuthenticateAsServer (BeginAuthenticateAsServer (
463                                 serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, null, null));
464                 }
465
466                 protected override void Dispose (bool disposing)
467                 {
468                         if (disposing) {
469                                 if (ssl_stream != null)
470                                         ssl_stream.Dispose ();
471                                 ssl_stream = null;
472                         }
473                         base.Dispose (disposing);
474                 }
475
476                 public virtual void EndAuthenticateAsClient (IAsyncResult asyncResult)
477                 {
478                         CheckConnectionAuthenticated ();
479
480                         if (CanRead)
481                                 ssl_stream.EndRead (asyncResult);
482                         else
483                                 ssl_stream.EndWrite (asyncResult);
484                 }
485
486                 public virtual void EndAuthenticateAsServer (IAsyncResult asyncResult)
487                 {
488                         CheckConnectionAuthenticated ();
489
490                         if (CanRead)
491                                 ssl_stream.EndRead (asyncResult);
492                         else
493                                 ssl_stream.EndWrite (asyncResult);
494                 }
495
496                 public override int EndRead (IAsyncResult asyncResult)
497                 {
498                         CheckConnectionAuthenticated ();
499
500                         return ssl_stream.EndRead (asyncResult);
501                 }
502
503                 public override void EndWrite (IAsyncResult asyncResult)
504                 {
505                         CheckConnectionAuthenticated ();
506
507                         ssl_stream.EndWrite (asyncResult);
508                 }
509
510                 public override void Flush ()
511                 {
512                         CheckConnectionAuthenticated ();
513
514                         InnerStream.Flush ();
515                 }
516
517                 public override int Read (byte[] buffer, int offset, int count)
518                 {
519                         return EndRead (BeginRead (buffer, offset, count, null, null));
520                 }
521
522                 public override long Seek (long offset, SeekOrigin origin)
523                 {
524                         throw new NotSupportedException ("This stream does not support seek operations");
525                 }
526
527                 public override void SetLength (long value)
528                 {
529                         InnerStream.SetLength (value);
530                 }
531
532                 public override void Write (byte[] buffer, int offset, int count)
533                 {
534                         EndWrite (BeginWrite (buffer, offset, count, null, null));
535                 }
536
537                 public void Write (byte[] buffer)
538                 {
539                         Write (buffer, 0, buffer.Length);
540                 }
541
542                 void CheckConnectionAuthenticated ()
543                 {
544                         if (!IsAuthenticated)
545                                 throw new InvalidOperationException ("This operation is invalid until it is successfully authenticated");
546                 }
547
548                 public virtual Task AuthenticateAsClientAsync (string targetHost)
549                 {
550                         return Task.Factory.FromAsync (BeginAuthenticateAsClient, EndAuthenticateAsClient, targetHost, null);
551                 }
552
553                 public virtual Task AuthenticateAsClientAsync (string targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
554                 {
555                         var t = Tuple.Create (targetHost, clientCertificates, enabledSslProtocols, checkCertificateRevocation, this);
556
557                         return Task.Factory.FromAsync ((callback, state) => {
558                                 var d = (Tuple<string, X509CertificateCollection, SslProtocols, bool, LegacySslStream>) state;
559                                 return d.Item5.BeginAuthenticateAsClient (d.Item1, d.Item2, d.Item3, d.Item4, callback, null);
560                         }, EndAuthenticateAsClient, t);
561                 }
562
563                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate)
564                 {
565                         return Task.Factory.FromAsync (BeginAuthenticateAsServer, EndAuthenticateAsServer, serverCertificate, null);
566                 }
567
568                 public virtual Task AuthenticateAsServerAsync (X509Certificate serverCertificate, bool clientCertificateRequired, SslProtocols enabledSslProtocols, bool checkCertificateRevocation)
569                 {
570                         var t = Tuple.Create (serverCertificate, clientCertificateRequired, enabledSslProtocols, checkCertificateRevocation, this);
571
572                         return Task.Factory.FromAsync ((callback, state) => {
573                                 var d = (Tuple<X509Certificate, bool, SslProtocols, bool, LegacySslStream>) state;
574                                 return d.Item5.BeginAuthenticateAsServer (d.Item1, d.Item2, d.Item3, d.Item4, callback, null);
575                         }, EndAuthenticateAsServer, t);
576                 }
577
578                 #endregion // Methods
579
580                 #region IMonoSslStream
581
582                 AuthenticatedStream IMonoSslStream.AuthenticatedStream {
583                         get { return this; }
584                 }
585
586                 TransportContext IMonoSslStream.TransportContext {
587                         get { throw new NotSupportedException (); }
588                 }
589
590                 MonoTlsProvider IMonoSslStream.Provider {
591                         get { return provider; }
592                 }
593
594                 MonoTlsConnectionInfo IMonoSslStream.GetConnectionInfo ()
595                 {
596                         return null;
597                 }
598
599                 #endregion
600         }
601 }
602
603 #endif