1 #region Copyright notice and license
2 
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System;
20 using System.Collections.Generic;
21 using Grpc.Core.Internal;
22 using Grpc.Core.Utils;
23 
24 namespace Grpc.Core
25 {
26     /// <summary>
27     /// Server side credentials.
28     /// </summary>
29     public abstract class ServerCredentials
30     {
31         static readonly ServerCredentials InsecureInstance = new InsecureServerCredentialsImpl();
32 
33         /// <summary>
34         /// Returns instance of credential that provides no security and
35         /// will result in creating an unsecure server port with no encryption whatsoever.
36         /// </summary>
37         public static ServerCredentials Insecure
38         {
39             get
40             {
41                 return InsecureInstance;
42             }
43         }
44 
45         /// <summary>
46         /// Creates native object for the credentials.
47         /// </summary>
48         /// <returns>The native credentials.</returns>
ToNativeCredentials()49         internal abstract ServerCredentialsSafeHandle ToNativeCredentials();
50 
51         private sealed class InsecureServerCredentialsImpl : ServerCredentials
52         {
ToNativeCredentials()53             internal override ServerCredentialsSafeHandle ToNativeCredentials()
54             {
55                 return null;
56             }
57         }
58     }
59 
60     /// <summary>
61     /// Modes of requesting client's SSL certificate by the server.
62     /// Corresponds to <c>grpc_ssl_client_certificate_request_type</c>.
63     /// </summary>
64     public enum SslClientCertificateRequestType {
65         /// <summary>
66         /// Server does not request client certificate.
67         /// The certificate presented by the client is not checked by the server at
68         /// all. (A client may present a self signed or signed certificate or not
69         /// present a certificate at all and any of those option would be accepted)
70         /// </summary>
71         DontRequest = 0,
72         /// <summary>
73         /// Server requests client certificate but does not enforce that the client
74         /// presents a certificate.
75         /// If the client presents a certificate, the client authentication is left to
76         /// the application (the necessary metadata will be available to the
77         /// application via authentication context properties, see grpc_auth_context).
78         /// The client's key certificate pair must be valid for the SSL connection to
79         /// be established.
80         ///</summary>
81         RequestButDontVerify,
82         /// <summary>
83         /// Server requests client certificate but does not enforce that the client
84         /// presents a certificate.
85         /// If the client presents a certificate, the client authentication is done by
86         /// the gRPC framework. (For a successful connection the client needs to either
87         /// present a certificate that can be verified against the root certificate
88         /// configured by the server or not present a certificate at all)
89         /// The client's key certificate pair must be valid for the SSL connection to
90         /// be established.
91         /// </summary>
92         RequestAndVerify,
93         /// <summary>
94         /// Server requests client certificate and enforces that the client presents a
95         /// certificate.
96         /// If the client presents a certificate, the client authentication is left to
97         /// the application (the necessary metadata will be available to the
98         /// application via authentication context properties, see grpc_auth_context).
99         /// The client's key certificate pair must be valid for the SSL connection to
100         /// be established.
101         ///</summary>
102         RequestAndRequireButDontVerify,
103         /// <summary>
104         /// Server requests client certificate and enforces that the client presents a
105         /// certificate.
106         /// The certificate presented by the client is verified by the gRPC framework.
107         /// (For a successful connection the client needs to present a certificate that
108         /// can be verified against the root certificate configured by the server)
109         /// The client's key certificate pair must be valid for the SSL connection to
110         /// be established.
111         /// </summary>
112         RequestAndRequireAndVerify,
113     }
114     /// <summary>
115     /// Server-side SSL credentials.
116     /// </summary>
117     public class SslServerCredentials : ServerCredentials
118     {
119         readonly IList<KeyCertificatePair> keyCertificatePairs;
120         readonly string rootCertificates;
121         readonly SslClientCertificateRequestType clientCertificateRequest;
122 
123         /// <summary>
124         /// Creates server-side SSL credentials.
125         /// </summary>
126         /// <param name="keyCertificatePairs">Key-certificates to use.</param>
127         /// <param name="rootCertificates">PEM encoded client root certificates used to authenticate client.</param>
128         /// <param name="forceClientAuth">Deprecated, use clientCertificateRequest overload instead.</param>
SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates, bool forceClientAuth)129         public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates, bool forceClientAuth)
130             : this(keyCertificatePairs, rootCertificates, forceClientAuth ? SslClientCertificateRequestType.RequestAndRequireAndVerify : SslClientCertificateRequestType.DontRequest)
131         {
132         }
133 
134         /// <summary>
135         /// Creates server-side SSL credentials.
136         /// </summary>
137         /// <param name="keyCertificatePairs">Key-certificates to use.</param>
138         /// <param name="rootCertificates">PEM encoded client root certificates used to authenticate client.</param>
139         /// <param name="clientCertificateRequest">Options for requesting and verifying client certificate.</param>
SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates, SslClientCertificateRequestType clientCertificateRequest)140         public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs, string rootCertificates, SslClientCertificateRequestType clientCertificateRequest)
141         {
142             this.keyCertificatePairs = new List<KeyCertificatePair>(keyCertificatePairs).AsReadOnly();
143             GrpcPreconditions.CheckArgument(this.keyCertificatePairs.Count > 0,
144                 "At least one KeyCertificatePair needs to be provided.");
145             if (clientCertificateRequest == SslClientCertificateRequestType.RequestAndRequireAndVerify)
146             {
147                 GrpcPreconditions.CheckNotNull(rootCertificates,
148                     "Cannot require and verify client certificate unless you provide rootCertificates.");
149             }
150             this.rootCertificates = rootCertificates;
151             this.clientCertificateRequest = clientCertificateRequest;
152         }
153 
154         /// <summary>
155         /// Creates server-side SSL credentials.
156         /// This constructor should be used if you do not wish to authenticate the client.
157         /// (client certificate won't be requested and checked by the server at all).
158         /// </summary>
159         /// <param name="keyCertificatePairs">Key-certificates to use.</param>
SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs)160         public SslServerCredentials(IEnumerable<KeyCertificatePair> keyCertificatePairs) : this(keyCertificatePairs, null, SslClientCertificateRequestType.DontRequest)
161         {
162         }
163 
164         /// <summary>
165         /// Key-certificate pairs.
166         /// </summary>
167         public IList<KeyCertificatePair> KeyCertificatePairs
168         {
169             get
170             {
171                 return this.keyCertificatePairs;
172             }
173         }
174 
175         /// <summary>
176         /// PEM encoded client root certificates.
177         /// </summary>
178         public string RootCertificates
179         {
180             get
181             {
182                 return this.rootCertificates;
183             }
184         }
185 
186         /// <summary>
187         /// Deprecated. If true, the authenticity of client check will be enforced.
188         /// </summary>
189         public bool ForceClientAuthentication
190         {
191             get
192             {
193                 return this.clientCertificateRequest == SslClientCertificateRequestType.RequestAndRequireAndVerify;
194             }
195         }
196 
197         /// <summary>
198         /// Mode of requesting certificate from client by the server.
199         /// </summary>
200         public SslClientCertificateRequestType ClientCertificateRequest
201         {
202             get
203             {
204                 return this.clientCertificateRequest;
205             }
206         }
207 
ToNativeCredentials()208         internal override ServerCredentialsSafeHandle ToNativeCredentials()
209         {
210             int count = keyCertificatePairs.Count;
211             string[] certChains = new string[count];
212             string[] keys = new string[count];
213             for (int i = 0; i < count; i++)
214             {
215                 certChains[i] = keyCertificatePairs[i].CertificateChain;
216                 keys[i] = keyCertificatePairs[i].PrivateKey;
217             }
218             return ServerCredentialsSafeHandle.CreateSslCredentials(rootCertificates, certChains, keys, clientCertificateRequest);
219         }
220     }
221 }
222