xref: /aosp_15_r20/external/grpc-grpc/src/cpp/common/tls_certificate_verifier.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 #include <stddef.h>
18 
19 #include <algorithm>
20 #include <functional>
21 #include <map>
22 #include <utility>
23 #include <vector>
24 
25 #include <grpc/grpc_security.h>
26 #include <grpc/status.h>
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 #include <grpc/support/string_util.h>
30 #include <grpcpp/impl/sync.h>
31 #include <grpcpp/security/tls_certificate_verifier.h>
32 #include <grpcpp/support/status.h>
33 #include <grpcpp/support/string_ref.h>
34 
35 namespace grpc {
36 namespace experimental {
37 
TlsCustomVerificationCheckRequest(grpc_tls_custom_verification_check_request * request)38 TlsCustomVerificationCheckRequest::TlsCustomVerificationCheckRequest(
39     grpc_tls_custom_verification_check_request* request)
40     : c_request_(request) {
41   GPR_ASSERT(c_request_ != nullptr);
42 }
43 
target_name() const44 grpc::string_ref TlsCustomVerificationCheckRequest::target_name() const {
45   return c_request_->target_name != nullptr ? c_request_->target_name : "";
46 }
47 
peer_cert() const48 grpc::string_ref TlsCustomVerificationCheckRequest::peer_cert() const {
49   return c_request_->peer_info.peer_cert != nullptr
50              ? c_request_->peer_info.peer_cert
51              : "";
52 }
53 
peer_cert_full_chain() const54 grpc::string_ref TlsCustomVerificationCheckRequest::peer_cert_full_chain()
55     const {
56   return c_request_->peer_info.peer_cert_full_chain != nullptr
57              ? c_request_->peer_info.peer_cert_full_chain
58              : "";
59 }
60 
common_name() const61 grpc::string_ref TlsCustomVerificationCheckRequest::common_name() const {
62   return c_request_->peer_info.common_name != nullptr
63              ? c_request_->peer_info.common_name
64              : "";
65 }
66 
verified_root_cert_subject() const67 grpc::string_ref TlsCustomVerificationCheckRequest::verified_root_cert_subject()
68     const {
69   return c_request_->peer_info.verified_root_cert_subject != nullptr
70              ? c_request_->peer_info.verified_root_cert_subject
71              : "";
72 }
73 
uri_names() const74 std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::uri_names()
75     const {
76   std::vector<grpc::string_ref> uri_names;
77   for (size_t i = 0; i < c_request_->peer_info.san_names.uri_names_size; ++i) {
78     uri_names.emplace_back(c_request_->peer_info.san_names.uri_names[i]);
79   }
80   return uri_names;
81 }
82 
dns_names() const83 std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::dns_names()
84     const {
85   std::vector<grpc::string_ref> dns_names;
86   for (size_t i = 0; i < c_request_->peer_info.san_names.dns_names_size; ++i) {
87     dns_names.emplace_back(c_request_->peer_info.san_names.dns_names[i]);
88   }
89   return dns_names;
90 }
91 
email_names() const92 std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::email_names()
93     const {
94   std::vector<grpc::string_ref> email_names;
95   for (size_t i = 0; i < c_request_->peer_info.san_names.email_names_size;
96        ++i) {
97     email_names.emplace_back(c_request_->peer_info.san_names.email_names[i]);
98   }
99   return email_names;
100 }
101 
ip_names() const102 std::vector<grpc::string_ref> TlsCustomVerificationCheckRequest::ip_names()
103     const {
104   std::vector<grpc::string_ref> ip_names;
105   for (size_t i = 0; i < c_request_->peer_info.san_names.ip_names_size; ++i) {
106     ip_names.emplace_back(c_request_->peer_info.san_names.ip_names[i]);
107   }
108   return ip_names;
109 }
110 
CertificateVerifier(grpc_tls_certificate_verifier * v)111 CertificateVerifier::CertificateVerifier(grpc_tls_certificate_verifier* v)
112     : verifier_(v) {}
113 
~CertificateVerifier()114 CertificateVerifier::~CertificateVerifier() {
115   grpc_tls_certificate_verifier_release(verifier_);
116 }
117 
Verify(TlsCustomVerificationCheckRequest * request,std::function<void (grpc::Status)> callback,grpc::Status * sync_status)118 bool CertificateVerifier::Verify(TlsCustomVerificationCheckRequest* request,
119                                  std::function<void(grpc::Status)> callback,
120                                  grpc::Status* sync_status) {
121   GPR_ASSERT(request != nullptr);
122   GPR_ASSERT(request->c_request() != nullptr);
123   {
124     internal::MutexLock lock(&mu_);
125     request_map_.emplace(request->c_request(), std::move(callback));
126   }
127   grpc_status_code status_code = GRPC_STATUS_OK;
128   char* error_details = nullptr;
129   bool is_done = grpc_tls_certificate_verifier_verify(
130       verifier_, request->c_request(), &AsyncCheckDone, this, &status_code,
131       &error_details);
132   if (is_done) {
133     if (status_code != GRPC_STATUS_OK) {
134       *sync_status = grpc::Status(static_cast<grpc::StatusCode>(status_code),
135                                   error_details);
136     }
137     internal::MutexLock lock(&mu_);
138     request_map_.erase(request->c_request());
139   }
140   gpr_free(error_details);
141   return is_done;
142 }
143 
Cancel(TlsCustomVerificationCheckRequest * request)144 void CertificateVerifier::Cancel(TlsCustomVerificationCheckRequest* request) {
145   GPR_ASSERT(request != nullptr);
146   GPR_ASSERT(request->c_request() != nullptr);
147   grpc_tls_certificate_verifier_cancel(verifier_, request->c_request());
148 }
149 
AsyncCheckDone(grpc_tls_custom_verification_check_request * request,void * callback_arg,grpc_status_code status,const char * error_details)150 void CertificateVerifier::AsyncCheckDone(
151     grpc_tls_custom_verification_check_request* request, void* callback_arg,
152     grpc_status_code status, const char* error_details) {
153   auto* self = static_cast<CertificateVerifier*>(callback_arg);
154   std::function<void(grpc::Status)> callback;
155   {
156     internal::MutexLock lock(&self->mu_);
157     auto it = self->request_map_.find(request);
158     if (it != self->request_map_.end()) {
159       callback = std::move(it->second);
160       self->request_map_.erase(it);
161     }
162   }
163   if (callback != nullptr) {
164     grpc::Status return_status;
165     if (status != GRPC_STATUS_OK) {
166       return_status =
167           grpc::Status(static_cast<grpc::StatusCode>(status), error_details);
168     }
169     callback(return_status);
170   }
171 }
172 
ExternalCertificateVerifier()173 ExternalCertificateVerifier::ExternalCertificateVerifier() {
174   base_ = new grpc_tls_certificate_verifier_external();
175   base_->user_data = this;
176   base_->verify = VerifyInCoreExternalVerifier;
177   base_->cancel = CancelInCoreExternalVerifier;
178   base_->destruct = DestructInCoreExternalVerifier;
179 }
180 
~ExternalCertificateVerifier()181 ExternalCertificateVerifier::~ExternalCertificateVerifier() { delete base_; }
182 
VerifyInCoreExternalVerifier(void * user_data,grpc_tls_custom_verification_check_request * request,grpc_tls_on_custom_verification_check_done_cb callback,void * callback_arg,grpc_status_code * sync_status,char ** sync_error_details)183 int ExternalCertificateVerifier::VerifyInCoreExternalVerifier(
184     void* user_data, grpc_tls_custom_verification_check_request* request,
185     grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
186     grpc_status_code* sync_status, char** sync_error_details) {
187   auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
188   TlsCustomVerificationCheckRequest* cpp_request = nullptr;
189   {
190     internal::MutexLock lock(&self->mu_);
191     auto pair = self->request_map_.emplace(
192         request, AsyncRequestState(callback, callback_arg, request));
193     GPR_ASSERT(pair.second);
194     cpp_request = &pair.first->second.cpp_request;
195   }
196   grpc::Status sync_current_verifier_status;
197   bool is_done = self->Verify(
198       cpp_request,
199       [self, request](grpc::Status status) {
200         grpc_tls_on_custom_verification_check_done_cb callback = nullptr;
201         void* callback_arg = nullptr;
202         {
203           internal::MutexLock lock(&self->mu_);
204           auto it = self->request_map_.find(request);
205           if (it != self->request_map_.end()) {
206             callback = it->second.callback;
207             callback_arg = it->second.callback_arg;
208             self->request_map_.erase(it);
209           }
210         }
211         if (callback != nullptr) {
212           callback(request, callback_arg,
213                    static_cast<grpc_status_code>(status.error_code()),
214                    status.error_message().c_str());
215         }
216       },
217       &sync_current_verifier_status);
218   if (is_done) {
219     if (!sync_current_verifier_status.ok()) {
220       *sync_status = static_cast<grpc_status_code>(
221           sync_current_verifier_status.error_code());
222       *sync_error_details =
223           gpr_strdup(sync_current_verifier_status.error_message().c_str());
224     }
225     internal::MutexLock lock(&self->mu_);
226     self->request_map_.erase(request);
227   }
228   return is_done;
229 }
230 
CancelInCoreExternalVerifier(void * user_data,grpc_tls_custom_verification_check_request * request)231 void ExternalCertificateVerifier::CancelInCoreExternalVerifier(
232     void* user_data, grpc_tls_custom_verification_check_request* request) {
233   auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
234   TlsCustomVerificationCheckRequest* cpp_request = nullptr;
235   {
236     internal::MutexLock lock(&self->mu_);
237     auto it = self->request_map_.find(request);
238     if (it != self->request_map_.end()) {
239       cpp_request = &it->second.cpp_request;
240     }
241   }
242   if (cpp_request != nullptr) {
243     self->Cancel(cpp_request);
244   }
245 }
246 
DestructInCoreExternalVerifier(void * user_data)247 void ExternalCertificateVerifier::DestructInCoreExternalVerifier(
248     void* user_data) {
249   auto* self = static_cast<ExternalCertificateVerifier*>(user_data);
250   delete self;
251 }
252 
NoOpCertificateVerifier()253 NoOpCertificateVerifier::NoOpCertificateVerifier()
254     : CertificateVerifier(grpc_tls_certificate_verifier_no_op_create()) {}
255 
HostNameCertificateVerifier()256 HostNameCertificateVerifier::HostNameCertificateVerifier()
257     : CertificateVerifier(grpc_tls_certificate_verifier_host_name_create()) {}
258 
259 }  // namespace experimental
260 }  // namespace grpc
261