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