1 //
2 //
3 // Copyright 2015-2016 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/composite/composite_credentials.h"
22
23 #include <cstring>
24 #include <memory>
25 #include <vector>
26
27 #include "absl/strings/str_cat.h"
28 #include "absl/strings/str_join.h"
29 #include "absl/strings/string_view.h"
30
31 #include <grpc/support/log.h>
32
33 #include "src/core/lib/debug/trace.h"
34 #include "src/core/lib/gprpp/ref_counted_ptr.h"
35 #include "src/core/lib/promise/try_seq.h"
36 #include "src/core/lib/surface/api_trace.h"
37
38 //
39 // grpc_composite_channel_credentials
40 //
41
type() const42 grpc_core::UniqueTypeName grpc_composite_channel_credentials::type() const {
43 static grpc_core::UniqueTypeName::Factory kFactory("Composite");
44 return kFactory.Create();
45 }
46
47 // -- Composite call credentials. --
48
49 grpc_core::ArenaPromise<absl::StatusOr<grpc_core::ClientMetadataHandle>>
GetRequestMetadata(grpc_core::ClientMetadataHandle initial_metadata,const grpc_call_credentials::GetRequestMetadataArgs * args)50 grpc_composite_call_credentials::GetRequestMetadata(
51 grpc_core::ClientMetadataHandle initial_metadata,
52 const grpc_call_credentials::GetRequestMetadataArgs* args) {
53 auto self = Ref();
54 return TrySeqIter(
55 inner_.begin(), inner_.end(), std::move(initial_metadata),
56 [self, args](const grpc_core::RefCountedPtr<grpc_call_credentials>& creds,
57 grpc_core::ClientMetadataHandle initial_metadata) {
58 return creds->GetRequestMetadata(std::move(initial_metadata), args);
59 });
60 }
61
Type()62 grpc_core::UniqueTypeName grpc_composite_call_credentials::Type() {
63 static grpc_core::UniqueTypeName::Factory kFactory("Composite");
64 return kFactory.Create();
65 }
66
debug_string()67 std::string grpc_composite_call_credentials::debug_string() {
68 std::vector<std::string> outputs;
69 for (auto& inner_cred : inner_) {
70 outputs.emplace_back(inner_cred->debug_string());
71 }
72 return absl::StrCat("CompositeCallCredentials{", absl::StrJoin(outputs, ","),
73 "}");
74 }
75
get_creds_array_size(const grpc_call_credentials * creds,bool is_composite)76 static size_t get_creds_array_size(const grpc_call_credentials* creds,
77 bool is_composite) {
78 return is_composite
79 ? static_cast<const grpc_composite_call_credentials*>(creds)
80 ->inner()
81 .size()
82 : 1;
83 }
84
push_to_inner(grpc_core::RefCountedPtr<grpc_call_credentials> creds,bool is_composite)85 void grpc_composite_call_credentials::push_to_inner(
86 grpc_core::RefCountedPtr<grpc_call_credentials> creds, bool is_composite) {
87 if (!is_composite) {
88 inner_.push_back(std::move(creds));
89 return;
90 }
91 auto composite_creds =
92 static_cast<grpc_composite_call_credentials*>(creds.get());
93 for (size_t i = 0; i < composite_creds->inner().size(); ++i) {
94 inner_.push_back(composite_creds->inner_[i]);
95 }
96 }
97
grpc_composite_call_credentials(grpc_core::RefCountedPtr<grpc_call_credentials> creds1,grpc_core::RefCountedPtr<grpc_call_credentials> creds2)98 grpc_composite_call_credentials::grpc_composite_call_credentials(
99 grpc_core::RefCountedPtr<grpc_call_credentials> creds1,
100 grpc_core::RefCountedPtr<grpc_call_credentials> creds2) {
101 const bool creds1_is_composite =
102 creds1->type() == grpc_composite_call_credentials::Type();
103 const bool creds2_is_composite =
104 creds2->type() == grpc_composite_call_credentials::Type();
105 const size_t size = get_creds_array_size(creds1.get(), creds1_is_composite) +
106 get_creds_array_size(creds2.get(), creds2_is_composite);
107 inner_.reserve(size);
108 push_to_inner(std::move(creds1), creds1_is_composite);
109 push_to_inner(std::move(creds2), creds2_is_composite);
110 min_security_level_ = GRPC_SECURITY_NONE;
111 for (size_t i = 0; i < inner_.size(); ++i) {
112 if (static_cast<int>(min_security_level_) <
113 static_cast<int>(inner_[i]->min_security_level())) {
114 min_security_level_ = inner_[i]->min_security_level();
115 }
116 }
117 }
118
119 static grpc_core::RefCountedPtr<grpc_call_credentials>
composite_call_credentials_create(grpc_core::RefCountedPtr<grpc_call_credentials> creds1,grpc_core::RefCountedPtr<grpc_call_credentials> creds2)120 composite_call_credentials_create(
121 grpc_core::RefCountedPtr<grpc_call_credentials> creds1,
122 grpc_core::RefCountedPtr<grpc_call_credentials> creds2) {
123 return grpc_core::MakeRefCounted<grpc_composite_call_credentials>(
124 std::move(creds1), std::move(creds2));
125 }
126
grpc_composite_call_credentials_create(grpc_call_credentials * creds1,grpc_call_credentials * creds2,void * reserved)127 grpc_call_credentials* grpc_composite_call_credentials_create(
128 grpc_call_credentials* creds1, grpc_call_credentials* creds2,
129 void* reserved) {
130 GRPC_API_TRACE(
131 "grpc_composite_call_credentials_create(creds1=%p, creds2=%p, "
132 "reserved=%p)",
133 3, (creds1, creds2, reserved));
134 GPR_ASSERT(reserved == nullptr);
135 GPR_ASSERT(creds1 != nullptr);
136 GPR_ASSERT(creds2 != nullptr);
137
138 return composite_call_credentials_create(creds1->Ref(), creds2->Ref())
139 .release();
140 }
141
142 // -- Composite channel credentials. --
143
144 grpc_core::RefCountedPtr<grpc_channel_security_connector>
create_security_connector(grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,const char * target,grpc_core::ChannelArgs * args)145 grpc_composite_channel_credentials::create_security_connector(
146 grpc_core::RefCountedPtr<grpc_call_credentials> call_creds,
147 const char* target, grpc_core::ChannelArgs* args) {
148 GPR_ASSERT(inner_creds_ != nullptr && call_creds_ != nullptr);
149 // If we are passed a call_creds, create a call composite to pass it
150 // downstream.
151 if (call_creds != nullptr) {
152 return inner_creds_->create_security_connector(
153 composite_call_credentials_create(call_creds_, std::move(call_creds)),
154 target, args);
155 } else {
156 return inner_creds_->create_security_connector(call_creds_, target, args);
157 }
158 }
159
grpc_composite_channel_credentials_create(grpc_channel_credentials * channel_creds,grpc_call_credentials * call_creds,void * reserved)160 grpc_channel_credentials* grpc_composite_channel_credentials_create(
161 grpc_channel_credentials* channel_creds, grpc_call_credentials* call_creds,
162 void* reserved) {
163 GPR_ASSERT(channel_creds != nullptr && call_creds != nullptr &&
164 reserved == nullptr);
165 GRPC_API_TRACE(
166 "grpc_composite_channel_credentials_create(channel_creds=%p, "
167 "call_creds=%p, reserved=%p)",
168 3, (channel_creds, call_creds, reserved));
169 return new grpc_composite_channel_credentials(channel_creds->Ref(),
170 call_creds->Ref());
171 }
172