• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2020 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 //
18 
19 #include "src/core/lib/security/credentials/xds/xds_credentials.h"
20 
21 #include <grpc/grpc_security_constants.h>
22 #include <grpc/impl/channel_arg_names.h>
23 #include <grpc/support/port_platform.h>
24 
25 #include "absl/log/check.h"
26 #include "absl/types/optional.h"
27 #include "src/core/lib/channel/channel_args.h"
28 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h"
29 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
30 #include "src/core/lib/security/credentials/tls/tls_credentials.h"
31 #include "src/core/lib/security/credentials/tls/tls_utils.h"
32 #include "src/core/load_balancing/xds/xds_channel_args.h"
33 #include "src/core/util/useful.h"
34 #include "src/core/xds/grpc/xds_certificate_provider.h"
35 
36 namespace grpc_core {
37 
38 namespace {
39 
XdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<StringMatcher> & matchers)40 bool XdsVerifySubjectAlternativeNames(
41     const char* const* subject_alternative_names,
42     size_t subject_alternative_names_size,
43     const std::vector<StringMatcher>& matchers) {
44   if (matchers.empty()) return true;
45   for (size_t i = 0; i < subject_alternative_names_size; ++i) {
46     for (const auto& matcher : matchers) {
47       if (matcher.type() == StringMatcher::Type::kExact) {
48         // For Exact match, use DNS rules for verifying SANs
49         // TODO(zhenlian): Right now, the SSL layer does not save the type of
50         // the SAN, so we are doing a DNS style verification for all SANs when
51         // the type is EXACT. When we expose the SAN type, change this to only
52         // do this verification when the SAN type is DNS and match type is
53         // kExact. For all other cases, we should use matcher.Match().
54         if (VerifySubjectAlternativeName(subject_alternative_names[i],
55                                          matcher.string_matcher())) {
56           return true;
57         }
58       } else {
59         if (matcher.Match(subject_alternative_names[i])) {
60           return true;
61         }
62       }
63     }
64   }
65   return false;
66 }
67 
68 }  // namespace
69 
70 //
71 // XdsCertificateVerifier
72 //
73 
XdsCertificateVerifier(RefCountedPtr<XdsCertificateProvider> xds_certificate_provider)74 XdsCertificateVerifier::XdsCertificateVerifier(
75     RefCountedPtr<XdsCertificateProvider> xds_certificate_provider)
76     : xds_certificate_provider_(std::move(xds_certificate_provider)) {}
77 
Verify(grpc_tls_custom_verification_check_request * request,std::function<void (absl::Status)>,absl::Status * sync_status)78 bool XdsCertificateVerifier::Verify(
79     grpc_tls_custom_verification_check_request* request,
80     std::function<void(absl::Status)>, absl::Status* sync_status) {
81   CHECK_NE(request, nullptr);
82   if (!XdsVerifySubjectAlternativeNames(
83           request->peer_info.san_names.uri_names,
84           request->peer_info.san_names.uri_names_size,
85           xds_certificate_provider_->san_matchers()) &&
86       !XdsVerifySubjectAlternativeNames(
87           request->peer_info.san_names.ip_names,
88           request->peer_info.san_names.ip_names_size,
89           xds_certificate_provider_->san_matchers()) &&
90       !XdsVerifySubjectAlternativeNames(
91           request->peer_info.san_names.dns_names,
92           request->peer_info.san_names.dns_names_size,
93           xds_certificate_provider_->san_matchers())) {
94     *sync_status = absl::Status(
95         absl::StatusCode::kUnauthenticated,
96         "SANs from certificate did not match SANs from xDS control plane");
97   }
98   return true;  // synchronous check
99 }
100 
Cancel(grpc_tls_custom_verification_check_request *)101 void XdsCertificateVerifier::Cancel(
102     grpc_tls_custom_verification_check_request*) {}
103 
CompareImpl(const grpc_tls_certificate_verifier * other) const104 int XdsCertificateVerifier::CompareImpl(
105     const grpc_tls_certificate_verifier* other) const {
106   auto* o = static_cast<const XdsCertificateVerifier*>(other);
107   if (xds_certificate_provider_ == nullptr ||
108       o->xds_certificate_provider_ == nullptr) {
109     return QsortCompare(xds_certificate_provider_,
110                         o->xds_certificate_provider_);
111   }
112   return xds_certificate_provider_->Compare(o->xds_certificate_provider_.get());
113 }
114 
type() const115 UniqueTypeName XdsCertificateVerifier::type() const {
116   static UniqueTypeName::Factory kFactory("Xds");
117   return kFactory.Create();
118 }
119 
TestOnlyXdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<StringMatcher> & matchers)120 bool TestOnlyXdsVerifySubjectAlternativeNames(
121     const char* const* subject_alternative_names,
122     size_t subject_alternative_names_size,
123     const std::vector<StringMatcher>& matchers) {
124   return XdsVerifySubjectAlternativeNames(
125       subject_alternative_names, subject_alternative_names_size, matchers);
126 }
127 
128 //
129 // XdsCredentials
130 //
131 
132 RefCountedPtr<grpc_channel_security_connector>
create_security_connector(RefCountedPtr<grpc_call_credentials> call_creds,const char * target_name,ChannelArgs * args)133 XdsCredentials::create_security_connector(
134     RefCountedPtr<grpc_call_credentials> call_creds, const char* target_name,
135     ChannelArgs* args) {
136   // TODO(yashykt): This arg will no longer need to be added after b/173119596
137   // is fixed.
138   *args = args->SetIfUnset(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, target_name);
139   RefCountedPtr<grpc_channel_security_connector> security_connector;
140   auto xds_certificate_provider = args->GetObjectRef<XdsCertificateProvider>();
141   if (xds_certificate_provider != nullptr) {
142     const bool watch_root = xds_certificate_provider->ProvidesRootCerts();
143     const bool use_system_root_certs =
144         xds_certificate_provider->UseSystemRootCerts();
145     const bool watch_identity =
146         xds_certificate_provider->ProvidesIdentityCerts();
147     if (watch_root || use_system_root_certs || watch_identity) {
148       auto tls_credentials_options =
149           MakeRefCounted<grpc_tls_credentials_options>();
150       if (watch_root || watch_identity) {
151         tls_credentials_options->set_certificate_provider(
152             xds_certificate_provider);
153         if (watch_root) {
154           tls_credentials_options->set_watch_root_cert(true);
155         }
156         if (watch_identity) {
157           tls_credentials_options->set_watch_identity_pair(true);
158         }
159       }
160       tls_credentials_options->set_verify_server_cert(true);
161       tls_credentials_options->set_certificate_verifier(
162           MakeRefCounted<XdsCertificateVerifier>(
163               std::move(xds_certificate_provider)));
164       tls_credentials_options->set_check_call_host(false);
165       auto tls_credentials =
166           MakeRefCounted<TlsCredentials>(std::move(tls_credentials_options));
167       return tls_credentials->create_security_connector(std::move(call_creds),
168                                                         target_name, args);
169     }
170   }
171   CHECK(fallback_credentials_ != nullptr);
172   return fallback_credentials_->create_security_connector(std::move(call_creds),
173                                                           target_name, args);
174 }
175 
Type()176 UniqueTypeName XdsCredentials::Type() {
177   static UniqueTypeName::Factory kFactory("Xds");
178   return kFactory.Create();
179 }
180 
181 //
182 // XdsServerCredentials
183 //
184 
185 RefCountedPtr<grpc_server_security_connector>
create_security_connector(const ChannelArgs & args)186 XdsServerCredentials::create_security_connector(const ChannelArgs& args) {
187   auto xds_certificate_provider = args.GetObjectRef<XdsCertificateProvider>();
188   // Identity certs are a must for TLS.
189   if (xds_certificate_provider != nullptr &&
190       xds_certificate_provider->ProvidesIdentityCerts()) {
191     auto tls_credentials_options =
192         MakeRefCounted<grpc_tls_credentials_options>();
193     tls_credentials_options->set_watch_identity_pair(true);
194     tls_credentials_options->set_certificate_provider(xds_certificate_provider);
195     if (xds_certificate_provider->ProvidesRootCerts()) {
196       tls_credentials_options->set_watch_root_cert(true);
197       tls_credentials_options->set_cert_request_type(
198           xds_certificate_provider->require_client_certificate()
199               ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
200               : GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY);
201     } else {
202       // Do not request client certificate if there is no way to verify.
203       tls_credentials_options->set_cert_request_type(
204           GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE);
205     }
206     auto tls_credentials = MakeRefCounted<TlsServerCredentials>(
207         std::move(tls_credentials_options));
208     return tls_credentials->create_security_connector(args);
209   }
210   return fallback_credentials_->create_security_connector(args);
211 }
212 
Type()213 UniqueTypeName XdsServerCredentials::Type() {
214   static UniqueTypeName::Factory kFactory("Xds");
215   return kFactory.Create();
216 }
217 
218 }  // namespace grpc_core
219 
grpc_xds_credentials_create(grpc_channel_credentials * fallback_credentials)220 grpc_channel_credentials* grpc_xds_credentials_create(
221     grpc_channel_credentials* fallback_credentials) {
222   CHECK_NE(fallback_credentials, nullptr);
223   return new grpc_core::XdsCredentials(fallback_credentials->Ref());
224 }
225 
grpc_xds_server_credentials_create(grpc_server_credentials * fallback_credentials)226 grpc_server_credentials* grpc_xds_server_credentials_create(
227     grpc_server_credentials* fallback_credentials) {
228   CHECK_NE(fallback_credentials, nullptr);
229   return new grpc_core::XdsServerCredentials(fallback_credentials->Ref());
230 }
231