ChannelCredentials.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #region Copyright notice and license
  2. // Copyright 2015 gRPC authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #endregion
  16. using System;
  17. using System.Collections.Generic;
  18. using System.Threading.Tasks;
  19. using Grpc.Core.Internal;
  20. using Grpc.Core.Utils;
  21. namespace Grpc.Core
  22. {
  23. /// <summary>
  24. /// Client-side channel credentials. Used for creation of a secure channel.
  25. /// </summary>
  26. public abstract class ChannelCredentials
  27. {
  28. static readonly ChannelCredentials InsecureInstance = new InsecureCredentialsImpl();
  29. readonly Lazy<ChannelCredentialsSafeHandle> cachedNativeCredentials;
  30. /// <summary>
  31. /// Creates a new instance of channel credentials
  32. /// </summary>
  33. public ChannelCredentials()
  34. {
  35. // Native credentials object need to be kept alive once initialized for subchannel sharing to work correctly
  36. // with secure connections. See https://github.com/grpc/grpc/issues/15207.
  37. // We rely on finalizer to clean up the native portion of ChannelCredentialsSafeHandle after the ChannelCredentials
  38. // instance becomes unused.
  39. this.cachedNativeCredentials = new Lazy<ChannelCredentialsSafeHandle>(() => CreateNativeCredentials());
  40. }
  41. /// <summary>
  42. /// Returns instance of credentials that provides no security and
  43. /// will result in creating an unsecure channel with no encryption whatsoever.
  44. /// </summary>
  45. public static ChannelCredentials Insecure
  46. {
  47. get
  48. {
  49. return InsecureInstance;
  50. }
  51. }
  52. /// <summary>
  53. /// Creates a new instance of <c>ChannelCredentials</c> class by composing
  54. /// given channel credentials with call credentials.
  55. /// </summary>
  56. /// <param name="channelCredentials">Channel credentials.</param>
  57. /// <param name="callCredentials">Call credentials.</param>
  58. /// <returns>The new composite <c>ChannelCredentials</c></returns>
  59. public static ChannelCredentials Create(ChannelCredentials channelCredentials, CallCredentials callCredentials)
  60. {
  61. return new CompositeChannelCredentials(channelCredentials, callCredentials);
  62. }
  63. /// <summary>
  64. /// Gets native object for the credentials, creating one if it already doesn't exist. May return null if insecure channel
  65. /// should be created. Caller must not call <c>Dispose()</c> on the returned native credentials as their lifetime
  66. /// is managed by this class (and instances of native credentials are cached).
  67. /// </summary>
  68. /// <returns>The native credentials.</returns>
  69. internal ChannelCredentialsSafeHandle GetNativeCredentials()
  70. {
  71. return cachedNativeCredentials.Value;
  72. }
  73. /// <summary>
  74. /// Creates a new native object for the credentials. May return null if insecure channel
  75. /// should be created. For internal use only, use <see cref="GetNativeCredentials"/> instead.
  76. /// </summary>
  77. /// <returns>The native credentials.</returns>
  78. internal abstract ChannelCredentialsSafeHandle CreateNativeCredentials();
  79. /// <summary>
  80. /// Returns <c>true</c> if this credential type allows being composed by <c>CompositeCredentials</c>.
  81. /// </summary>
  82. internal virtual bool IsComposable
  83. {
  84. get { return false; }
  85. }
  86. private sealed class InsecureCredentialsImpl : ChannelCredentials
  87. {
  88. internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
  89. {
  90. return null;
  91. }
  92. }
  93. }
  94. /// <summary>
  95. /// Client-side SSL credentials.
  96. /// </summary>
  97. public sealed class SslCredentials : ChannelCredentials
  98. {
  99. readonly string rootCertificates;
  100. readonly KeyCertificatePair keyCertificatePair;
  101. /// <summary>
  102. /// Creates client-side SSL credentials loaded from
  103. /// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable.
  104. /// If that fails, gets the roots certificates from a well known place on disk.
  105. /// </summary>
  106. public SslCredentials() : this(null, null)
  107. {
  108. }
  109. /// <summary>
  110. /// Creates client-side SSL credentials from
  111. /// a string containing PEM encoded root certificates.
  112. /// </summary>
  113. public SslCredentials(string rootCertificates) : this(rootCertificates, null)
  114. {
  115. }
  116. /// <summary>
  117. /// Creates client-side SSL credentials.
  118. /// </summary>
  119. /// <param name="rootCertificates">string containing PEM encoded server root certificates.</param>
  120. /// <param name="keyCertificatePair">a key certificate pair.</param>
  121. public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair)
  122. {
  123. this.rootCertificates = rootCertificates;
  124. this.keyCertificatePair = keyCertificatePair;
  125. }
  126. /// <summary>
  127. /// PEM encoding of the server root certificates.
  128. /// </summary>
  129. public string RootCertificates
  130. {
  131. get
  132. {
  133. return this.rootCertificates;
  134. }
  135. }
  136. /// <summary>
  137. /// Client side key and certificate pair.
  138. /// If null, client will not use key and certificate pair.
  139. /// </summary>
  140. public KeyCertificatePair KeyCertificatePair
  141. {
  142. get
  143. {
  144. return this.keyCertificatePair;
  145. }
  146. }
  147. // Composing composite makes no sense.
  148. internal override bool IsComposable
  149. {
  150. get { return true; }
  151. }
  152. internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
  153. {
  154. return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
  155. }
  156. }
  157. /// <summary>
  158. /// Credentials that allow composing one <see cref="ChannelCredentials"/> object and
  159. /// one or more <see cref="CallCredentials"/> objects into a single <see cref="ChannelCredentials"/>.
  160. /// </summary>
  161. internal sealed class CompositeChannelCredentials : ChannelCredentials
  162. {
  163. readonly ChannelCredentials channelCredentials;
  164. readonly CallCredentials callCredentials;
  165. /// <summary>
  166. /// Initializes a new instance of <c>CompositeChannelCredentials</c> class.
  167. /// The resulting credentials object will be composite of all the credentials specified as parameters.
  168. /// </summary>
  169. /// <param name="channelCredentials">channelCredentials to compose</param>
  170. /// <param name="callCredentials">channelCredentials to compose</param>
  171. public CompositeChannelCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials)
  172. {
  173. this.channelCredentials = GrpcPreconditions.CheckNotNull(channelCredentials);
  174. this.callCredentials = GrpcPreconditions.CheckNotNull(callCredentials);
  175. GrpcPreconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
  176. }
  177. internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
  178. {
  179. using (var callCreds = callCredentials.ToNativeCredentials())
  180. {
  181. var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCredentials.GetNativeCredentials(), callCreds);
  182. if (nativeComposite.IsInvalid)
  183. {
  184. throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
  185. }
  186. return nativeComposite;
  187. }
  188. }
  189. }
  190. }