SslStream.cs 13 KB

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