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