1//
2// Copyright 2021 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//
16
17#ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H
18#define GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H
19
20#include <functional>
21#include <map>
22#include <memory>
23#include <utility>
24#include <vector>
25
26#include <grpc/grpc_security_constants.h>
27#include <grpc/status.h>
28#include <grpc/support/log.h>
29#include <grpcpp/impl/codegen/grpc_library.h>
30#include <grpcpp/impl/codegen/sync.h>
31#include <grpcpp/impl/grpc_library.h>
32#include <grpcpp/support/config.h>
33#include <grpcpp/support/string_ref.h>
34
35// TODO(yihuazhang): remove the forward declaration here and include
36// <grpc/grpc_security.h> directly once the insecure builds are cleaned up.
37typedef struct grpc_tls_custom_verification_check_request
38 grpc_tls_custom_verification_check_request;
39typedef struct grpc_tls_certificate_verifier grpc_tls_certificate_verifier;
40typedef struct grpc_tls_certificate_verifier_external
41 grpc_tls_certificate_verifier_external;
42typedef void (*grpc_tls_on_custom_verification_check_done_cb)(
43 grpc_tls_custom_verification_check_request* request, void* callback_arg,
44 grpc_status_code status, const char* error_details);
45extern "C" grpc_tls_certificate_verifier*
46grpc_tls_certificate_verifier_external_create(
47 grpc_tls_certificate_verifier_external* external_verifier);
48
49namespace grpc {
50namespace experimental {
51
52// Contains the verification-related information associated with a connection
53// request. Users should not directly create or destroy this request object, but
54// shall interact with it through CertificateVerifier's Verify() and Cancel().
55class TlsCustomVerificationCheckRequest {
56 public:
57 explicit TlsCustomVerificationCheckRequest(
58 grpc_tls_custom_verification_check_request* request);
59 ~TlsCustomVerificationCheckRequest() {}
60
61 grpc::string_ref target_name() const;
62 grpc::string_ref peer_cert() const;
63 grpc::string_ref peer_cert_full_chain() const;
64 grpc::string_ref common_name() const;
65 std::vector<grpc::string_ref> uri_names() const;
66 std::vector<grpc::string_ref> dns_names() const;
67 std::vector<grpc::string_ref> email_names() const;
68 std::vector<grpc::string_ref> ip_names() const;
69
70 grpc_tls_custom_verification_check_request* c_request() { return c_request_; }
71
72 private:
73 grpc_tls_custom_verification_check_request* c_request_ = nullptr;
74};
75
76// The base class of all internal verifier implementations, and the ultimate
77// class that all external verifiers will eventually be transformed into.
78// To implement a custom verifier, do not extend this class; instead,
79// implement a subclass of ExternalCertificateVerifier. Note that custom
80// verifier implementations can compose their functionality with existing
81// implementations of this interface, such as HostnameVerifier, by delegating
82// to an instance of that class.
83class CertificateVerifier {
84 public:
85 explicit CertificateVerifier(grpc_tls_certificate_verifier* v);
86
87 ~CertificateVerifier();
88
89 // Verifies a connection request, based on the logic specified in an internal
90 // verifier. The check on each internal verifier could be either synchronous
91 // or asynchronous, and we will need to use return value to know.
92 //
93 // request: the verification information associated with this request
94 // callback: This will only take effect if the verifier is asynchronous.
95 // The function that gRPC will invoke when the verifier has already
96 // completed its asynchronous check. Callers can use this function
97 // to perform any additional checks. The input parameter of the
98 // std::function indicates the status of the verifier check.
99 // sync_status: This will only be useful if the verifier is synchronous.
100 // The status of the verifier as it has already done it's
101 // synchronous check.
102 // return: return true if executed synchronously, otherwise return false
103 bool Verify(TlsCustomVerificationCheckRequest* request,
104 std::function<void(grpc::Status)> callback,
105 grpc::Status* sync_status);
106
107 // Cancels a verification request previously started via Verify().
108 // Used when the connection attempt times out or is cancelled while an async
109 // verification request is pending.
110 //
111 // request: the verification information associated with this request
112 void Cancel(TlsCustomVerificationCheckRequest* request);
113
114 // Gets the core verifier used internally.
115 grpc_tls_certificate_verifier* c_verifier() { return verifier_; }
116
117 private:
118 static void AsyncCheckDone(
119 grpc_tls_custom_verification_check_request* request, void* callback_arg,
120 grpc_status_code status, const char* error_details);
121
122 grpc_tls_certificate_verifier* verifier_ = nullptr;
123 grpc::internal::Mutex mu_;
124 std::map<grpc_tls_custom_verification_check_request*,
125 std::function<void(grpc::Status)>>
126 request_map_ ABSL_GUARDED_BY(mu_);
127};
128
129// The base class of all external, user-specified verifiers. Users should
130// inherit this class to implement a custom verifier.
131// Note that while implementing the custom verifier that extends this class, it
132// is possible to compose an existing ExternalCertificateVerifier or
133// CertificateVerifier, inside the Verify() and Cancel() function of the new
134// custom verifier.
135class ExternalCertificateVerifier {
136 public:
137 // A factory method for creating a |CertificateVerifier| from this class. All
138 // the user-implemented verifiers should use this function to be converted to
139 // verifiers compatible with |TlsCredentialsOptions|.
140 // The resulting CertificateVerifier takes ownership of the newly instantiated
141 // Subclass.
142 template <typename Subclass, typename... Args>
143 static std::shared_ptr<CertificateVerifier> Create(Args&&... args) {
144 grpc::internal::GrpcLibraryInitializer g_gli_initializer;
145 g_gli_initializer.summon();
146 auto* external_verifier = new Subclass(std::forward<Args>(args)...);
147 return std::make_shared<CertificateVerifier>(
148 grpc_tls_certificate_verifier_external_create(
149 external_verifier->base_));
150 }
151
152 // The verification logic that will be performed after the TLS handshake
153 // completes. Implementers can choose to do their checks synchronously or
154 // asynchronously.
155 //
156 // request: the verification information associated with this request
157 // callback: This should only be used if your check is done asynchronously.
158 // When the asynchronous work is done, invoke this callback function
159 // with the proper status, indicating the success or the failure of
160 // the check. The implementer MUST NOT invoke this |callback| in the
161 // same thread before Verify() returns, otherwise it can lead to
162 // deadlocks.
163 // sync_status: This should only be used if your check is done synchronously.
164 // Modifies this value to indicate the success or the failure of
165 // the check.
166 // return: return true if your check is done synchronously, otherwise return
167 // false
168 virtual bool Verify(TlsCustomVerificationCheckRequest* request,
169 std::function<void(grpc::Status)> callback,
170 grpc::Status* sync_status) = 0;
171
172 // Cancels a verification request previously started via Verify().
173 // Used when the connection attempt times out or is cancelled while an async
174 // verification request is pending. The implementation should abort whatever
175 // async operation it is waiting for and quickly invoke the callback that was
176 // passed to Verify() with a status indicating the cancellation.
177 //
178 // request: the verification information associated with this request
179 virtual void Cancel(TlsCustomVerificationCheckRequest* request) = 0;
180
181 protected:
182 ExternalCertificateVerifier();
183
184 virtual ~ExternalCertificateVerifier();
185
186 private:
187 struct AsyncRequestState {
188 AsyncRequestState(grpc_tls_on_custom_verification_check_done_cb cb,
189 void* arg,
190 grpc_tls_custom_verification_check_request* request)
191 : callback(cb), callback_arg(arg), cpp_request(request) {}
192
193 grpc_tls_on_custom_verification_check_done_cb callback;
194 void* callback_arg;
195 TlsCustomVerificationCheckRequest cpp_request;
196 };
197
198 static int VerifyInCoreExternalVerifier(
199 void* user_data, grpc_tls_custom_verification_check_request* request,
200 grpc_tls_on_custom_verification_check_done_cb callback,
201 void* callback_arg, grpc_status_code* sync_status,
202 char** sync_error_details);
203
204 static void CancelInCoreExternalVerifier(
205 void* user_data, grpc_tls_custom_verification_check_request* request);
206
207 static void DestructInCoreExternalVerifier(void* user_data);
208
209 // TODO(yihuazhang): after the insecure build is removed, make this an object
210 // member instead of a pointer.
211 grpc_tls_certificate_verifier_external* base_ = nullptr;
212 grpc::internal::Mutex mu_;
213 std::map<grpc_tls_custom_verification_check_request*, AsyncRequestState>
214 request_map_ ABSL_GUARDED_BY(mu_);
215};
216
217// A CertificateVerifier that doesn't perform any additional checks other than
218// certificate verification, if specified.
219// Note: using this solely without any other authentication mechanisms on the
220// peer identity will leave your applications to the MITM(Man-In-The-Middle)
221// attacks. Users should avoid doing so in production environments.
222class NoOpCertificateVerifier : public CertificateVerifier {
223 public:
224 NoOpCertificateVerifier();
225};
226
227// A CertificateVerifier that will perform hostname verification, to see if the
228// target name set from the client side matches the identity information
229// specified on the server's certificate.
230class HostNameCertificateVerifier : public CertificateVerifier {
231 public:
232 HostNameCertificateVerifier();
233};
234
235} // namespace experimental
236} // namespace grpc
237
238#endif // GRPCPP_SECURITY_TLS_CERTIFICATE_VERIFIER_H
239

source code of include/grpcpp/security/tls_certificate_verifier.h