• 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 <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