1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/support/port_platform.h>
16
17 #include "src/core/lib/security/authorization/evaluate_args.h"
18
19 #include "src/core/lib/address_utils/parse_address.h"
20 #include "src/core/lib/gprpp/host_port.h"
21 #include "src/core/lib/slice/slice_utils.h"
22
23 namespace grpc_core {
24
25 namespace {
26
GetAuthPropertyValue(grpc_auth_context * context,const char * property_name)27 absl::string_view GetAuthPropertyValue(grpc_auth_context* context,
28 const char* property_name) {
29 grpc_auth_property_iterator it =
30 grpc_auth_context_find_properties_by_name(context, property_name);
31 const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
32 if (prop == nullptr) {
33 gpr_log(GPR_DEBUG, "No value found for %s property.", property_name);
34 return "";
35 }
36 if (grpc_auth_property_iterator_next(&it) != nullptr) {
37 gpr_log(GPR_DEBUG, "Multiple values found for %s property.", property_name);
38 return "";
39 }
40 return absl::string_view(prop->value, prop->value_length);
41 }
42
ParseEndpointUri(absl::string_view uri_text,std::string * address,int * port)43 void ParseEndpointUri(absl::string_view uri_text, std::string* address,
44 int* port) {
45 absl::StatusOr<URI> uri = URI::Parse(uri_text);
46 if (!uri.ok()) {
47 gpr_log(GPR_DEBUG, "Failed to parse uri.");
48 return;
49 }
50 absl::string_view host_view;
51 absl::string_view port_view;
52 if (!SplitHostPort(uri->path(), &host_view, &port_view)) {
53 gpr_log(GPR_DEBUG, "Failed to split %s into host and port.",
54 uri->path().c_str());
55 return;
56 }
57 *address = std::string(host_view);
58 if (!absl::SimpleAtoi(port_view, port)) {
59 gpr_log(GPR_DEBUG, "Port %s is out of range or null.",
60 std::string(port_view).c_str());
61 }
62 }
63
64 } // namespace
65
PerChannelArgs(grpc_auth_context * auth_context,grpc_endpoint * endpoint)66 EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
67 grpc_endpoint* endpoint) {
68 if (auth_context != nullptr) {
69 transport_security_type = GetAuthPropertyValue(
70 auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
71 spiffe_id =
72 GetAuthPropertyValue(auth_context, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
73 common_name =
74 GetAuthPropertyValue(auth_context, GRPC_X509_CN_PROPERTY_NAME);
75 }
76 if (endpoint != nullptr) {
77 ParseEndpointUri(grpc_endpoint_get_local_address(endpoint), &local_address,
78 &local_port);
79 ParseEndpointUri(grpc_endpoint_get_peer(endpoint), &peer_address,
80 &peer_port);
81 }
82 }
83
GetPath() const84 absl::string_view EvaluateArgs::GetPath() const {
85 absl::string_view path;
86 if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) {
87 grpc_linked_mdelem* elem = metadata_->idx.named.path;
88 const grpc_slice& val = GRPC_MDVALUE(elem->md);
89 path = StringViewFromSlice(val);
90 }
91 return path;
92 }
93
GetHost() const94 absl::string_view EvaluateArgs::GetHost() const {
95 absl::string_view host;
96 if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) {
97 grpc_linked_mdelem* elem = metadata_->idx.named.host;
98 const grpc_slice& val = GRPC_MDVALUE(elem->md);
99 host = StringViewFromSlice(val);
100 }
101 return host;
102 }
103
GetMethod() const104 absl::string_view EvaluateArgs::GetMethod() const {
105 absl::string_view method;
106 if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) {
107 grpc_linked_mdelem* elem = metadata_->idx.named.method;
108 const grpc_slice& val = GRPC_MDVALUE(elem->md);
109 method = StringViewFromSlice(val);
110 }
111 return method;
112 }
113
GetHeaders() const114 std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
115 const {
116 std::multimap<absl::string_view, absl::string_view> headers;
117 if (metadata_ == nullptr) {
118 return headers;
119 }
120 for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr;
121 elem = elem->next) {
122 const grpc_slice& key = GRPC_MDKEY(elem->md);
123 const grpc_slice& val = GRPC_MDVALUE(elem->md);
124 headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
125 }
126 return headers;
127 }
128
GetHeaderValue(absl::string_view key,std::string * concatenated_value) const129 absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue(
130 absl::string_view key, std::string* concatenated_value) const {
131 if (metadata_ == nullptr) {
132 return absl::nullopt;
133 }
134 return grpc_metadata_batch_get_value(metadata_, key, concatenated_value);
135 }
136
GetLocalAddress() const137 absl::string_view EvaluateArgs::GetLocalAddress() const {
138 if (channel_args_ == nullptr) {
139 return "";
140 }
141 return channel_args_->local_address;
142 }
143
GetLocalPort() const144 int EvaluateArgs::GetLocalPort() const {
145 if (channel_args_ == nullptr) {
146 return 0;
147 }
148 return channel_args_->local_port;
149 }
150
GetPeerAddress() const151 absl::string_view EvaluateArgs::GetPeerAddress() const {
152 if (channel_args_ == nullptr) {
153 return "";
154 }
155 return channel_args_->peer_address;
156 }
157
GetPeerPort() const158 int EvaluateArgs::GetPeerPort() const {
159 if (channel_args_ == nullptr) {
160 return 0;
161 }
162 return channel_args_->peer_port;
163 }
164
GetTransportSecurityType() const165 absl::string_view EvaluateArgs::GetTransportSecurityType() const {
166 if (channel_args_ == nullptr) {
167 return "";
168 }
169 return channel_args_->transport_security_type;
170 }
171
GetSpiffeId() const172 absl::string_view EvaluateArgs::GetSpiffeId() const {
173 if (channel_args_ == nullptr) {
174 return "";
175 }
176 return channel_args_->spiffe_id;
177 }
178
GetCommonName() const179 absl::string_view EvaluateArgs::GetCommonName() const {
180 if (channel_args_ == nullptr) {
181 return "";
182 }
183 return channel_args_->common_name;
184 }
185
186 } // namespace grpc_core
187