1 /*
2 *
3 * Copyright 2015 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 <grpc/grpc.h>
22
23 #include <string.h>
24
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/string_util.h>
27
28 #include "src/core/ext/filters/client_channel/client_channel.h"
29 #include "src/core/ext/filters/client_channel/resolver_registry.h"
30 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
31 #include "src/core/lib/channel/channel_args.h"
32 #include "src/core/lib/gprpp/memory.h"
33 #include "src/core/lib/iomgr/sockaddr_utils.h"
34 #include "src/core/lib/security/credentials/credentials.h"
35 #include "src/core/lib/security/security_connector/security_connector.h"
36 #include "src/core/lib/security/transport/target_authority_table.h"
37 #include "src/core/lib/slice/slice_hash_table.h"
38 #include "src/core/lib/slice/slice_internal.h"
39 #include "src/core/lib/surface/api_trace.h"
40 #include "src/core/lib/surface/channel.h"
41 #include "src/core/lib/uri/uri_parser.h"
42
43 namespace grpc_core {
44
45 class Chttp2SecureClientChannelFactory : public ClientChannelFactory {
46 public:
CreateSubchannel(const grpc_channel_args * args)47 Subchannel* CreateSubchannel(const grpc_channel_args* args) override {
48 grpc_channel_args* new_args = GetSecureNamingChannelArgs(args);
49 if (new_args == nullptr) {
50 gpr_log(GPR_ERROR,
51 "Failed to create channel args during subchannel creation.");
52 return nullptr;
53 }
54 grpc_connector* connector = grpc_chttp2_connector_create();
55 Subchannel* s = Subchannel::Create(connector, new_args);
56 grpc_connector_unref(connector);
57 grpc_channel_args_destroy(new_args);
58 return s;
59 }
60
CreateChannel(const char * target,const grpc_channel_args * args)61 grpc_channel* CreateChannel(const char* target,
62 const grpc_channel_args* args) override {
63 if (target == nullptr) {
64 gpr_log(GPR_ERROR, "cannot create channel with NULL target name");
65 return nullptr;
66 }
67 // Add channel arg containing the server URI.
68 UniquePtr<char> canonical_target =
69 ResolverRegistry::AddDefaultPrefixIfNeeded(target);
70 grpc_arg arg = grpc_channel_arg_string_create(
71 const_cast<char*>(GRPC_ARG_SERVER_URI), canonical_target.get());
72 const char* to_remove[] = {GRPC_ARG_SERVER_URI};
73 grpc_channel_args* new_args =
74 grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
75 grpc_channel* channel =
76 grpc_channel_create(target, new_args, GRPC_CLIENT_CHANNEL, nullptr);
77 grpc_channel_args_destroy(new_args);
78 return channel;
79 }
80
81 private:
GetSecureNamingChannelArgs(const grpc_channel_args * args)82 static grpc_channel_args* GetSecureNamingChannelArgs(
83 const grpc_channel_args* args) {
84 grpc_channel_credentials* channel_credentials =
85 grpc_channel_credentials_find_in_args(args);
86 if (channel_credentials == nullptr) {
87 gpr_log(GPR_ERROR,
88 "Can't create subchannel: channel credentials missing for secure "
89 "channel.");
90 return nullptr;
91 }
92 // Make sure security connector does not already exist in args.
93 if (grpc_security_connector_find_in_args(args) != nullptr) {
94 gpr_log(GPR_ERROR,
95 "Can't create subchannel: security connector already present in "
96 "channel args.");
97 return nullptr;
98 }
99 // To which address are we connecting? By default, use the server URI.
100 const grpc_arg* server_uri_arg =
101 grpc_channel_args_find(args, GRPC_ARG_SERVER_URI);
102 const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg);
103 GPR_ASSERT(server_uri_str != nullptr);
104 grpc_uri* server_uri =
105 grpc_uri_parse(server_uri_str, true /* suppress errors */);
106 GPR_ASSERT(server_uri != nullptr);
107 const TargetAuthorityTable* target_authority_table =
108 FindTargetAuthorityTableInArgs(args);
109 UniquePtr<char> authority;
110 if (target_authority_table != nullptr) {
111 // Find the authority for the target.
112 const char* target_uri_str =
113 Subchannel::GetUriFromSubchannelAddressArg(args);
114 grpc_uri* target_uri =
115 grpc_uri_parse(target_uri_str, false /* suppress errors */);
116 GPR_ASSERT(target_uri != nullptr);
117 if (target_uri->path[0] != '\0') { // "path" may be empty
118 const grpc_slice key = grpc_slice_from_static_string(
119 target_uri->path[0] == '/' ? target_uri->path + 1
120 : target_uri->path);
121 const UniquePtr<char>* value = target_authority_table->Get(key);
122 if (value != nullptr) authority.reset(gpr_strdup(value->get()));
123 grpc_slice_unref_internal(key);
124 }
125 grpc_uri_destroy(target_uri);
126 }
127 // If the authority hasn't already been set (either because no target
128 // authority table was present or because the target was not present
129 // in the table), fall back to using the original server URI.
130 if (authority == nullptr) {
131 authority = ResolverRegistry::GetDefaultAuthority(server_uri_str);
132 }
133 grpc_arg args_to_add[2];
134 size_t num_args_to_add = 0;
135 if (grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) == nullptr) {
136 // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY,
137 // add the arg, setting it to the value just obtained.
138 args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
139 const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), authority.get());
140 }
141 grpc_channel_args* args_with_authority =
142 grpc_channel_args_copy_and_add(args, args_to_add, num_args_to_add);
143 grpc_uri_destroy(server_uri);
144 // Create the security connector using the credentials and target name.
145 grpc_channel_args* new_args_from_connector = nullptr;
146 RefCountedPtr<grpc_channel_security_connector>
147 subchannel_security_connector =
148 channel_credentials->create_security_connector(
149 /*call_creds=*/nullptr, authority.get(), args_with_authority,
150 &new_args_from_connector);
151 if (subchannel_security_connector == nullptr) {
152 gpr_log(GPR_ERROR,
153 "Failed to create secure subchannel for secure name '%s'",
154 authority.get());
155 grpc_channel_args_destroy(args_with_authority);
156 return nullptr;
157 }
158 grpc_arg new_security_connector_arg =
159 grpc_security_connector_to_arg(subchannel_security_connector.get());
160 grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
161 new_args_from_connector != nullptr ? new_args_from_connector
162 : args_with_authority,
163 &new_security_connector_arg, 1);
164 subchannel_security_connector.reset(DEBUG_LOCATION, "lb_channel_create");
165 if (new_args_from_connector != nullptr) {
166 grpc_channel_args_destroy(new_args_from_connector);
167 }
168 grpc_channel_args_destroy(args_with_authority);
169 return new_args;
170 }
171 };
172
173 } // namespace grpc_core
174
175 namespace {
176
177 grpc_core::Chttp2SecureClientChannelFactory* g_factory;
178 gpr_once g_factory_once = GPR_ONCE_INIT;
179
FactoryInit()180 void FactoryInit() {
181 g_factory = grpc_core::New<grpc_core::Chttp2SecureClientChannelFactory>();
182 }
183
184 } // namespace
185
186 // Create a secure client channel:
187 // Asynchronously: - resolve target
188 // - connect to it (trying alternatives as presented)
189 // - perform handshakes
grpc_secure_channel_create(grpc_channel_credentials * creds,const char * target,const grpc_channel_args * args,void * reserved)190 grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds,
191 const char* target,
192 const grpc_channel_args* args,
193 void* reserved) {
194 grpc_core::ExecCtx exec_ctx;
195 GRPC_API_TRACE(
196 "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
197 "reserved=%p)",
198 4, ((void*)creds, target, (void*)args, (void*)reserved));
199 GPR_ASSERT(reserved == nullptr);
200 grpc_channel* channel = nullptr;
201 if (creds != nullptr) {
202 // Add channel args containing the client channel factory and channel
203 // credentials.
204 gpr_once_init(&g_factory_once, FactoryInit);
205 grpc_arg args_to_add[] = {
206 grpc_core::ClientChannelFactory::CreateChannelArg(g_factory),
207 grpc_channel_credentials_to_arg(creds)};
208 grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
209 args, args_to_add, GPR_ARRAY_SIZE(args_to_add));
210 new_args = creds->update_arguments(new_args);
211 // Create channel.
212 channel = g_factory->CreateChannel(target, new_args);
213 // Clean up.
214 grpc_channel_args_destroy(new_args);
215 }
216 return channel != nullptr ? channel
217 : grpc_lame_client_channel_create(
218 target, GRPC_STATUS_INTERNAL,
219 "Failed to create secure client channel");
220 }
221