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 <grpc/support/port_platform.h>
20
21 #include "src/core/lib/security/credentials/xds/xds_credentials.h"
22
23 #include "src/core/ext/xds/xds_certificate_provider.h"
24 #include "src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h"
25 #include "src/core/lib/security/credentials/tls/tls_credentials.h"
26 #include "src/core/lib/security/credentials/tls/tls_utils.h"
27 #include "src/core/lib/uri/uri_parser.h"
28
29 namespace grpc_core {
30
31 const char kCredentialsTypeXds[] = "Xds";
32
33 namespace {
34
XdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<XdsApi::StringMatcher> & matchers)35 bool XdsVerifySubjectAlternativeNames(
36 const char* const* subject_alternative_names,
37 size_t subject_alternative_names_size,
38 const std::vector<XdsApi::StringMatcher>& matchers) {
39 if (matchers.empty()) return true;
40 for (size_t i = 0; i < subject_alternative_names_size; ++i) {
41 for (const auto& matcher : matchers) {
42 if (matcher.type() == XdsApi::StringMatcher::StringMatcherType::EXACT) {
43 // For EXACT match, use DNS rules for verifying SANs
44 // TODO(zhenlian): Right now, the SSL layer does not save the type of
45 // the SAN, so we are doing a DNS style verification for all SANs when
46 // the type is EXACT. When we expose the SAN type, change this to only
47 // do this verification when the SAN type is DNS and match type is
48 // EXACT. For all other cases, we should use matcher.Match().
49 if (VerifySubjectAlternativeName(subject_alternative_names[i],
50 matcher.string_matcher())) {
51 return true;
52 }
53 } else {
54 if (matcher.Match(subject_alternative_names[i])) {
55 return true;
56 }
57 }
58 }
59 }
60 return false;
61 }
62
ServerAuthCheckSchedule(void * config_user_data,grpc_tls_server_authorization_check_arg * arg)63 int ServerAuthCheckSchedule(void* config_user_data,
64 grpc_tls_server_authorization_check_arg* arg) {
65 XdsCertificateProvider* xds_certificate_provider =
66 static_cast<XdsCertificateProvider*>(config_user_data);
67 if (XdsVerifySubjectAlternativeNames(
68 arg->subject_alternative_names, arg->subject_alternative_names_size,
69 xds_certificate_provider->subject_alternative_name_matchers())) {
70 arg->success = 1;
71 arg->status = GRPC_STATUS_OK;
72 } else {
73 arg->success = 0;
74 arg->status = GRPC_STATUS_UNAUTHENTICATED;
75 if (arg->error_details) {
76 arg->error_details->set_error_details(
77 "SANs from certificate did not match SANs from xDS control plane");
78 }
79 }
80
81 return 0; /* synchronous check */
82 }
83
ServerAuthCheckDestroy(void * config_user_data)84 void ServerAuthCheckDestroy(void* config_user_data) {
85 XdsCertificateProvider* xds_certificate_provider =
86 static_cast<XdsCertificateProvider*>(config_user_data);
87 xds_certificate_provider->Unref();
88 }
89
90 } // namespace
91
TestOnlyXdsVerifySubjectAlternativeNames(const char * const * subject_alternative_names,size_t subject_alternative_names_size,const std::vector<XdsApi::StringMatcher> & matchers)92 bool TestOnlyXdsVerifySubjectAlternativeNames(
93 const char* const* subject_alternative_names,
94 size_t subject_alternative_names_size,
95 const std::vector<XdsApi::StringMatcher>& matchers) {
96 return XdsVerifySubjectAlternativeNames(
97 subject_alternative_names, subject_alternative_names_size, matchers);
98 }
99
100 //
101 // XdsCredentials
102 //
103
104 RefCountedPtr<grpc_channel_security_connector>
create_security_connector(RefCountedPtr<grpc_call_credentials> call_creds,const char * target_name,const grpc_channel_args * args,grpc_channel_args ** new_args)105 XdsCredentials::create_security_connector(
106 RefCountedPtr<grpc_call_credentials> call_creds, const char* target_name,
107 const grpc_channel_args* args, grpc_channel_args** new_args) {
108 auto xds_certificate_provider =
109 XdsCertificateProvider::GetFromChannelArgs(args);
110 // TODO(yashykt): This arg will no longer need to be added after b/173119596
111 // is fixed.
112 grpc_arg override_arg = grpc_channel_arg_string_create(
113 const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
114 const_cast<char*>(target_name));
115 const char* override_arg_name = GRPC_SSL_TARGET_NAME_OVERRIDE_ARG;
116 const grpc_channel_args* temp_args = args;
117 if (grpc_channel_args_find(args, override_arg_name) == nullptr) {
118 temp_args = grpc_channel_args_copy_and_add_and_remove(
119 args, &override_arg_name, 1, &override_arg, 1);
120 }
121 RefCountedPtr<grpc_channel_security_connector> security_connector;
122 if (xds_certificate_provider != nullptr) {
123 auto tls_credentials_options =
124 MakeRefCounted<grpc_tls_credentials_options>();
125 tls_credentials_options->set_certificate_provider(xds_certificate_provider);
126 if (xds_certificate_provider->ProvidesRootCerts()) {
127 tls_credentials_options->set_watch_root_cert(true);
128 }
129 if (xds_certificate_provider->ProvidesIdentityCerts()) {
130 tls_credentials_options->set_watch_identity_pair(true);
131 }
132 tls_credentials_options->set_server_verification_option(
133 GRPC_TLS_SKIP_HOSTNAME_VERIFICATION);
134 tls_credentials_options->set_server_authorization_check_config(
135 MakeRefCounted<grpc_tls_server_authorization_check_config>(
136 xds_certificate_provider->Ref().release(), ServerAuthCheckSchedule,
137 nullptr, ServerAuthCheckDestroy));
138 auto tls_credentials =
139 MakeRefCounted<TlsCredentials>(std::move(tls_credentials_options));
140 security_connector = tls_credentials->create_security_connector(
141 std::move(call_creds), target_name, temp_args, new_args);
142 } else {
143 GPR_ASSERT(fallback_credentials_ != nullptr);
144 security_connector = fallback_credentials_->create_security_connector(
145 std::move(call_creds), target_name, temp_args, new_args);
146 }
147 if (temp_args != args) {
148 grpc_channel_args_destroy(temp_args);
149 }
150 return security_connector;
151 }
152
153 //
154 // XdsServerCredentials
155 //
156
157 RefCountedPtr<grpc_server_security_connector>
create_security_connector()158 XdsServerCredentials::create_security_connector() {
159 // TODO(yashkt): Fill this
160 return fallback_credentials_->create_security_connector();
161 }
162
163 } // namespace grpc_core
164
grpc_xds_credentials_create(grpc_channel_credentials * fallback_credentials)165 grpc_channel_credentials* grpc_xds_credentials_create(
166 grpc_channel_credentials* fallback_credentials) {
167 GPR_ASSERT(fallback_credentials != nullptr);
168 return new grpc_core::XdsCredentials(fallback_credentials->Ref());
169 }
170
grpc_xds_server_credentials_create(grpc_server_credentials * fallback_credentials)171 grpc_server_credentials* grpc_xds_server_credentials_create(
172 grpc_server_credentials* fallback_credentials) {
173 GPR_ASSERT(fallback_credentials != nullptr);
174 return new grpc_core::XdsServerCredentials(fallback_credentials->Ref());
175 }
176