• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
18 
19 #include <grpc/support/alloc.h>
20 #include <grpc/support/port_platform.h>
21 #include <grpc/support/string_util.h>
22 #include <string.h>
23 
24 #include <string>
25 #include <utility>
26 
27 #include "absl/log/check.h"
28 #include "absl/strings/string_view.h"
29 #include "src/core/lib/debug/trace.h"
30 #include "src/core/lib/iomgr/exec_ctx.h"
31 #include "src/core/lib/security/credentials/tls/tls_utils.h"
32 #include "src/core/util/host_port.h"
33 
34 namespace grpc_core {
35 
36 //
37 // ExternalCertificateVerifier
38 //
39 
Verify(grpc_tls_custom_verification_check_request * request,std::function<void (absl::Status)> callback,absl::Status * sync_status)40 bool ExternalCertificateVerifier::Verify(
41     grpc_tls_custom_verification_check_request* request,
42     std::function<void(absl::Status)> callback, absl::Status* sync_status) {
43   {
44     MutexLock lock(&mu_);
45     request_map_.emplace(request, std::move(callback));
46   }
47   // Invoke the caller-specified verification logic embedded in
48   // external_verifier_.
49   grpc_status_code status_code = GRPC_STATUS_OK;
50   char* error_details = nullptr;
51   bool is_done = external_verifier_->verify(external_verifier_->user_data,
52                                             request, &OnVerifyDone, this,
53                                             &status_code, &error_details);
54   if (is_done) {
55     if (status_code != GRPC_STATUS_OK) {
56       *sync_status = absl::Status(static_cast<absl::StatusCode>(status_code),
57                                   error_details);
58     }
59     MutexLock lock(&mu_);
60     request_map_.erase(request);
61   }
62   gpr_free(error_details);
63   return is_done;
64 }
65 
type() const66 UniqueTypeName ExternalCertificateVerifier::type() const {
67   static UniqueTypeName::Factory kFactory("External");
68   return kFactory.Create();
69 }
70 
OnVerifyDone(grpc_tls_custom_verification_check_request * request,void * callback_arg,grpc_status_code status,const char * error_details)71 void ExternalCertificateVerifier::OnVerifyDone(
72     grpc_tls_custom_verification_check_request* request, void* callback_arg,
73     grpc_status_code status, const char* error_details) {
74   ExecCtx exec_ctx;
75   auto* self = static_cast<ExternalCertificateVerifier*>(callback_arg);
76   std::function<void(absl::Status)> callback;
77   {
78     MutexLock lock(&self->mu_);
79     auto it = self->request_map_.find(request);
80     if (it != self->request_map_.end()) {
81       callback = std::move(it->second);
82       self->request_map_.erase(it);
83     }
84   }
85   if (callback != nullptr) {
86     absl::Status return_status;
87     if (status != GRPC_STATUS_OK) {
88       return_status =
89           absl::Status(static_cast<absl::StatusCode>(status), error_details);
90     }
91     callback(return_status);
92   }
93 }
94 
95 //
96 // NoOpCertificateVerifier
97 //
98 
type() const99 UniqueTypeName NoOpCertificateVerifier::type() const {
100   static UniqueTypeName::Factory kFactory("NoOp");
101   return kFactory.Create();
102 }
103 
104 //
105 // HostNameCertificateVerifier
106 //
107 
Verify(grpc_tls_custom_verification_check_request * request,std::function<void (absl::Status)>,absl::Status * sync_status)108 bool HostNameCertificateVerifier::Verify(
109     grpc_tls_custom_verification_check_request* request,
110     std::function<void(absl::Status)>, absl::Status* sync_status) {
111   CHECK_NE(request, nullptr);
112   // Extract the target name, and remove its port.
113   const char* target_name = request->target_name;
114   if (target_name == nullptr) {
115     *sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
116                                 "Target name is not specified.");
117     return true;  // synchronous check
118   }
119   absl::string_view target_host;
120   absl::string_view ignored_port;
121   SplitHostPort(target_name, &target_host, &ignored_port);
122   if (target_host.empty()) {
123     *sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
124                                 "Failed to split hostname and port.");
125     return true;  // synchronous check
126   }
127   // IPv6 zone-id should not be included in comparisons.
128   const size_t zone_id = target_host.find('%');
129   if (zone_id != absl::string_view::npos) {
130     target_host.remove_suffix(target_host.size() - zone_id);
131   }
132   // Perform the hostname check.
133   // First check the DNS field. We allow prefix or suffix wildcard matching.
134   char** dns_names = request->peer_info.san_names.dns_names;
135   size_t dns_names_size = request->peer_info.san_names.dns_names_size;
136   if (dns_names != nullptr && dns_names_size > 0) {
137     for (size_t i = 0; i < dns_names_size; ++i) {
138       const char* dns_name = dns_names[i];
139       // We are using the target name sent from the client as a matcher to match
140       // against identity name on the peer cert.
141       if (VerifySubjectAlternativeName(dns_name, std::string(target_host))) {
142         return true;  // synchronous check
143       }
144     }
145   }
146   // Then check the IP address. We only allow exact matching.
147   char** ip_names = request->peer_info.san_names.ip_names;
148   size_t ip_names_size = request->peer_info.san_names.ip_names_size;
149   if (ip_names != nullptr && ip_names_size > 0) {
150     for (size_t i = 0; i < ip_names_size; ++i) {
151       const char* ip_name = ip_names[i];
152       if (target_host == ip_name) {
153         return true;  // synchronous check
154       }
155     }
156   }
157   // If there's no SAN, try the CN.
158   if (dns_names_size == 0) {
159     const char* common_name = request->peer_info.common_name;
160     // We are using the target name sent from the client as a matcher to match
161     // against identity name on the peer cert.
162     if (common_name != nullptr &&
163         VerifySubjectAlternativeName(common_name, std::string(target_host))) {
164       return true;  // synchronous check
165     }
166   }
167   *sync_status = absl::Status(absl::StatusCode::kUnauthenticated,
168                               "Hostname Verification Check failed.");
169   return true;  // synchronous check
170 }
171 
type() const172 UniqueTypeName HostNameCertificateVerifier::type() const {
173   static UniqueTypeName::Factory kFactory("Hostname");
174   return kFactory.Create();
175 }
176 
177 }  // namespace grpc_core
178 
179 //
180 // Wrapper APIs declared in grpc_security.h
181 //
182 
grpc_tls_certificate_verifier_verify(grpc_tls_certificate_verifier * verifier,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 grpc_tls_certificate_verifier_verify(
184     grpc_tls_certificate_verifier* verifier,
185     grpc_tls_custom_verification_check_request* request,
186     grpc_tls_on_custom_verification_check_done_cb callback, void* callback_arg,
187     grpc_status_code* sync_status, char** sync_error_details) {
188   grpc_core::ExecCtx exec_ctx;
189   std::function<void(absl::Status)> async_cb =
190       [callback, request, callback_arg](absl::Status async_status) {
191         callback(request, callback_arg,
192                  static_cast<grpc_status_code>(async_status.code()),
193                  std::string(async_status.message()).c_str());
194       };
195   absl::Status sync_status_cpp;
196   bool is_done = verifier->Verify(request, async_cb, &sync_status_cpp);
197   if (is_done) {
198     if (!sync_status_cpp.ok()) {
199       *sync_status = static_cast<grpc_status_code>(sync_status_cpp.code());
200       *sync_error_details =
201           gpr_strdup(std::string(sync_status_cpp.message()).c_str());
202     }
203   }
204   return is_done;
205 }
206 
grpc_tls_certificate_verifier_cancel(grpc_tls_certificate_verifier * verifier,grpc_tls_custom_verification_check_request * request)207 void grpc_tls_certificate_verifier_cancel(
208     grpc_tls_certificate_verifier* verifier,
209     grpc_tls_custom_verification_check_request* request) {
210   grpc_core::ExecCtx exec_ctx;
211   verifier->Cancel(request);
212 }
213 
grpc_tls_certificate_verifier_external_create(grpc_tls_certificate_verifier_external * external_verifier)214 grpc_tls_certificate_verifier* grpc_tls_certificate_verifier_external_create(
215     grpc_tls_certificate_verifier_external* external_verifier) {
216   grpc_core::ExecCtx exec_ctx;
217   return new grpc_core::ExternalCertificateVerifier(external_verifier);
218 }
219 
grpc_tls_certificate_verifier_no_op_create()220 grpc_tls_certificate_verifier* grpc_tls_certificate_verifier_no_op_create() {
221   grpc_core::ExecCtx exec_ctx;
222   return new grpc_core::NoOpCertificateVerifier();
223 }
224 
225 grpc_tls_certificate_verifier*
grpc_tls_certificate_verifier_host_name_create()226 grpc_tls_certificate_verifier_host_name_create() {
227   grpc_core::ExecCtx exec_ctx;
228   return new grpc_core::HostNameCertificateVerifier();
229 }
230 
grpc_tls_certificate_verifier_release(grpc_tls_certificate_verifier * verifier)231 void grpc_tls_certificate_verifier_release(
232     grpc_tls_certificate_verifier* verifier) {
233   GRPC_TRACE_LOG(api, INFO)
234       << "grpc_tls_certificate_verifier_release(verifier=" << verifier << ")";
235   grpc_core::ExecCtx exec_ctx;
236   if (verifier != nullptr) verifier->Unref();
237 }
238