1 /*
2  *
3  * Copyright 2018 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/tls/tls_credentials.h"
22 
23 #include <cstring>
24 
25 #include <grpc/grpc.h>
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/log.h>
28 #include <grpc/support/string_util.h>
29 
30 #include "src/core/lib/channel/channel_args.h"
31 #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_verifier.h"
32 #include "src/core/lib/security/security_connector/tls/tls_security_connector.h"
33 
34 #define GRPC_CREDENTIALS_TYPE_TLS "Tls"
35 
36 namespace {
37 
CredentialOptionSanityCheck(grpc_tls_credentials_options * options,bool is_client)38 bool CredentialOptionSanityCheck(grpc_tls_credentials_options* options,
39                                  bool is_client) {
40   if (options == nullptr) {
41     gpr_log(GPR_ERROR, "TLS credentials options is nullptr.");
42     return false;
43   }
44   // In the following conditions, there won't be any issues, but it might
45   // indicate callers are doing something wrong with the API.
46   if (is_client && options->cert_request_type() !=
47                        GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE) {
48     gpr_log(GPR_ERROR,
49             "Client's credentials options should not set cert_request_type.");
50   }
51   if (!is_client && !options->verify_server_cert()) {
52     gpr_log(GPR_ERROR,
53             "Server's credentials options should not set verify_server_cert.");
54   }
55   // In the following conditions, there could be severe security issues.
56   if (is_client && options->certificate_verifier() == nullptr) {
57     // If no verifier is specified on the client side, use the hostname verifier
58     // as default. Users who want to bypass all the verifier check should
59     // implement an external verifier instead.
60     gpr_log(GPR_INFO,
61             "No verifier specified on the client side. Using default hostname "
62             "verifier");
63     options->set_certificate_verifier(
64         grpc_core::MakeRefCounted<grpc_core::HostNameCertificateVerifier>());
65   }
66   return true;
67 }
68 
69 }  // namespace
70 
TlsCredentials(grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)71 TlsCredentials::TlsCredentials(
72     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
73     : grpc_channel_credentials(GRPC_CREDENTIALS_TYPE_TLS),
74       options_(std::move(options)) {}
75 
~TlsCredentials()76 TlsCredentials::~TlsCredentials() {}
77 
78 grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,const char * target_name,const grpc_channel_args * args,grpc_channel_args ** new_args)79 TlsCredentials::create_security_connector(
80     grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
81     const char* target_name, const grpc_channel_args* args,
82     grpc_channel_args** new_args) {
83   const char* overridden_target_name = nullptr;
84   tsi_ssl_session_cache* ssl_session_cache = nullptr;
85   for (size_t i = 0; args != nullptr && i < args->num_args; i++) {
86     grpc_arg* arg = &args->args[i];
87     if (strcmp(arg->key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG) == 0 &&
88         arg->type == GRPC_ARG_STRING) {
89       overridden_target_name = arg->value.string;
90     }
91     if (strcmp(arg->key, GRPC_SSL_SESSION_CACHE_ARG) == 0 &&
92         arg->type == GRPC_ARG_POINTER) {
93       ssl_session_cache =
94           static_cast<tsi_ssl_session_cache*>(arg->value.pointer.p);
95     }
96   }
97   grpc_core::RefCountedPtr<grpc_channel_security_connector> sc =
98       grpc_core::TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector(
99           this->Ref(), options_, std::move(call_creds), target_name,
100           overridden_target_name, ssl_session_cache);
101   if (sc == nullptr) {
102     return nullptr;
103   }
104   if (args != nullptr) {
105     grpc_arg new_arg = grpc_channel_arg_string_create(
106         const_cast<char*>(GRPC_ARG_HTTP2_SCHEME), const_cast<char*>("https"));
107     *new_args = grpc_channel_args_copy_and_add(args, &new_arg, 1);
108   }
109   return sc;
110 }
111 
TlsServerCredentials(grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)112 TlsServerCredentials::TlsServerCredentials(
113     grpc_core::RefCountedPtr<grpc_tls_credentials_options> options)
114     : grpc_server_credentials(GRPC_CREDENTIALS_TYPE_TLS),
115       options_(std::move(options)) {}
116 
~TlsServerCredentials()117 TlsServerCredentials::~TlsServerCredentials() {}
118 
119 grpc_core::RefCountedPtr<grpc_server_security_connector>
create_security_connector(const grpc_channel_args *)120 TlsServerCredentials::create_security_connector(
121     const grpc_channel_args* /* args */) {
122   return grpc_core::TlsServerSecurityConnector::
123       CreateTlsServerSecurityConnector(this->Ref(), options_);
124 }
125 
126 /** -- Wrapper APIs declared in grpc_security.h -- **/
127 
grpc_tls_credentials_create(grpc_tls_credentials_options * options)128 grpc_channel_credentials* grpc_tls_credentials_create(
129     grpc_tls_credentials_options* options) {
130   if (!CredentialOptionSanityCheck(options, true /* is_client */)) {
131     return nullptr;
132   }
133   return new TlsCredentials(
134       grpc_core::RefCountedPtr<grpc_tls_credentials_options>(options));
135 }
136 
grpc_tls_server_credentials_create(grpc_tls_credentials_options * options)137 grpc_server_credentials* grpc_tls_server_credentials_create(
138     grpc_tls_credentials_options* options) {
139   if (!CredentialOptionSanityCheck(options, false /* is_client */)) {
140     return nullptr;
141   }
142   return new TlsServerCredentials(
143       grpc_core::RefCountedPtr<grpc_tls_credentials_options>(options));
144 }
145