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