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 "src/core/lib/security/authorization/evaluate_args.h"
16
17 #include <grpc/grpc_security_constants.h>
18 #include <grpc/support/port_platform.h>
19 #include <string.h>
20
21 #include "absl/log/log.h"
22 #include "absl/status/status.h"
23 #include "absl/status/statusor.h"
24 #include "absl/strings/match.h"
25 #include "absl/strings/numbers.h"
26 #include "src/core/handshaker/endpoint_info/endpoint_info_handshaker.h"
27 #include "src/core/lib/address_utils/parse_address.h"
28 #include "src/core/lib/security/credentials/tls/tls_utils.h"
29 #include "src/core/lib/slice/slice.h"
30 #include "src/core/util/host_port.h"
31 #include "src/core/util/uri.h"
32
33 namespace grpc_core {
34
35 namespace {
36
ParseEndpointUri(absl::string_view uri_text)37 EvaluateArgs::PerChannelArgs::Address ParseEndpointUri(
38 absl::string_view uri_text) {
39 EvaluateArgs::PerChannelArgs::Address address;
40 absl::StatusOr<URI> uri = URI::Parse(uri_text);
41 if (!uri.ok()) {
42 VLOG(2) << "Failed to parse uri.";
43 return address;
44 }
45 absl::string_view host_view;
46 absl::string_view port_view;
47 if (!SplitHostPort(uri->path(), &host_view, &port_view)) {
48 VLOG(2) << "Failed to split " << uri->path() << " into host and port.";
49 return address;
50 }
51 if (!absl::SimpleAtoi(port_view, &address.port)) {
52 VLOG(2) << "Port " << port_view << " is out of range or null.";
53 }
54 address.address_str = std::string(host_view);
55 auto resolved_address = StringToSockaddr(uri->path());
56 if (!resolved_address.ok()) {
57 VLOG(2) << "Address \"" << uri->path()
58 << "\" is not IPv4/IPv6. Error: " << resolved_address.status();
59 memset(&address.address, 0, sizeof(address.address));
60 } else {
61 address.address = *resolved_address;
62 }
63 return address;
64 }
65
66 } // namespace
67
PerChannelArgs(grpc_auth_context * auth_context,const ChannelArgs & args)68 EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context,
69 const ChannelArgs& args) {
70 if (auth_context != nullptr) {
71 transport_security_type = GetAuthPropertyValue(
72 auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
73 spiffe_id =
74 GetAuthPropertyValue(auth_context, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
75 uri_sans = GetAuthPropertyArray(auth_context, GRPC_PEER_URI_PROPERTY_NAME);
76 dns_sans = GetAuthPropertyArray(auth_context, GRPC_PEER_DNS_PROPERTY_NAME);
77 common_name =
78 GetAuthPropertyValue(auth_context, GRPC_X509_CN_PROPERTY_NAME);
79 subject =
80 GetAuthPropertyValue(auth_context, GRPC_X509_SUBJECT_PROPERTY_NAME);
81 }
82 local_address = ParseEndpointUri(
83 args.GetString(GRPC_ARG_ENDPOINT_LOCAL_ADDRESS).value_or(""));
84 peer_address = ParseEndpointUri(
85 args.GetString(GRPC_ARG_ENDPOINT_PEER_ADDRESS).value_or(""));
86 }
87
GetPath() const88 absl::string_view EvaluateArgs::GetPath() const {
89 if (metadata_ != nullptr) {
90 const auto* path = metadata_->get_pointer(HttpPathMetadata());
91 if (path != nullptr) {
92 return path->as_string_view();
93 }
94 }
95 return absl::string_view();
96 }
97
GetAuthority() const98 absl::string_view EvaluateArgs::GetAuthority() const {
99 absl::string_view authority;
100 if (metadata_ != nullptr) {
101 if (auto* authority_md = metadata_->get_pointer(HttpAuthorityMetadata())) {
102 authority = authority_md->as_string_view();
103 }
104 }
105 return authority;
106 }
107
GetMethod() const108 absl::string_view EvaluateArgs::GetMethod() const {
109 if (metadata_ != nullptr) {
110 auto method_md = metadata_->get(HttpMethodMetadata());
111 if (method_md.has_value()) {
112 return HttpMethodMetadata::Encode(*method_md).as_string_view();
113 }
114 }
115 return absl::string_view();
116 }
117
GetHeaderValue(absl::string_view key,std::string * concatenated_value) const118 absl::optional<absl::string_view> EvaluateArgs::GetHeaderValue(
119 absl::string_view key, std::string* concatenated_value) const {
120 if (metadata_ == nullptr) {
121 return absl::nullopt;
122 }
123 if (absl::EqualsIgnoreCase(key, "te")) {
124 return absl::nullopt;
125 }
126 if (absl::EqualsIgnoreCase(key, "host")) {
127 // Maps legacy host header to :authority.
128 return GetAuthority();
129 }
130 return metadata_->GetStringValue(key, concatenated_value);
131 }
132
GetLocalAddress() const133 grpc_resolved_address EvaluateArgs::GetLocalAddress() const {
134 if (channel_args_ == nullptr) {
135 return {};
136 }
137 return channel_args_->local_address.address;
138 }
139
GetLocalAddressString() const140 absl::string_view EvaluateArgs::GetLocalAddressString() const {
141 if (channel_args_ == nullptr) {
142 return "";
143 }
144 return channel_args_->local_address.address_str;
145 }
146
GetLocalPort() const147 int EvaluateArgs::GetLocalPort() const {
148 if (channel_args_ == nullptr) {
149 return 0;
150 }
151 return channel_args_->local_address.port;
152 }
153
GetPeerAddress() const154 grpc_resolved_address EvaluateArgs::GetPeerAddress() const {
155 if (channel_args_ == nullptr) {
156 return {};
157 }
158 return channel_args_->peer_address.address;
159 }
160
GetPeerAddressString() const161 absl::string_view EvaluateArgs::GetPeerAddressString() const {
162 if (channel_args_ == nullptr) {
163 return "";
164 }
165 return channel_args_->peer_address.address_str;
166 }
167
GetPeerPort() const168 int EvaluateArgs::GetPeerPort() const {
169 if (channel_args_ == nullptr) {
170 return 0;
171 }
172 return channel_args_->peer_address.port;
173 }
174
GetTransportSecurityType() const175 absl::string_view EvaluateArgs::GetTransportSecurityType() const {
176 if (channel_args_ == nullptr) {
177 return "";
178 }
179 return channel_args_->transport_security_type;
180 }
181
GetSpiffeId() const182 absl::string_view EvaluateArgs::GetSpiffeId() const {
183 if (channel_args_ == nullptr) {
184 return "";
185 }
186 return channel_args_->spiffe_id;
187 }
188
GetUriSans() const189 std::vector<absl::string_view> EvaluateArgs::GetUriSans() const {
190 if (channel_args_ == nullptr) {
191 return {};
192 }
193 return channel_args_->uri_sans;
194 }
195
GetDnsSans() const196 std::vector<absl::string_view> EvaluateArgs::GetDnsSans() const {
197 if (channel_args_ == nullptr) {
198 return {};
199 }
200 return channel_args_->dns_sans;
201 }
202
GetCommonName() const203 absl::string_view EvaluateArgs::GetCommonName() const {
204 if (channel_args_ == nullptr) {
205 return "";
206 }
207 return channel_args_->common_name;
208 }
209
GetSubject() const210 absl::string_view EvaluateArgs::GetSubject() const {
211 if (channel_args_ == nullptr) {
212 return "";
213 }
214 return channel_args_->subject;
215 }
216
217 } // namespace grpc_core
218