xref: /aosp_15_r20/external/grpc-grpc/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2018 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 #include "test/core/tsi/alts/fake_handshaker/fake_handshaker_server.h"
19 
20 #include <memory>
21 #include <sstream>
22 #include <string>
23 
24 #include "absl/strings/str_format.h"
25 
26 #include <grpc/grpc.h>
27 #include <grpc/support/log.h>
28 #include <grpcpp/impl/sync.h>
29 #include <grpcpp/security/server_credentials.h>
30 #include <grpcpp/server.h>
31 #include <grpcpp/server_builder.h>
32 #include <grpcpp/server_context.h>
33 #include <grpcpp/support/async_stream.h>
34 
35 #include "src/core/lib/gprpp/crash.h"
36 #include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
37 #include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
38 #include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
39 
40 // Fake handshake messages.
41 constexpr char kClientInitFrame[] = "ClientInit";
42 constexpr char kServerFrame[] = "ServerInitAndFinished";
43 constexpr char kClientFinishFrame[] = "ClientFinished";
44 // Error messages.
45 constexpr char kInvalidFrameError[] = "Invalid input frame.";
46 constexpr char kWrongStateError[] = "Wrong handshake state.";
47 
48 namespace grpc {
49 namespace gcp {
50 
51 // FakeHandshakeService implements a fake handshaker service using a fake key
52 // exchange protocol. The fake key exchange protocol is a 3-message protocol:
53 // - Client first sends ClientInit message to Server.
54 // - Server then sends ServerInitAndFinished message back to Client.
55 // - Client finally sends ClientFinished message to Server.
56 // This fake handshaker service is intended for ALTS integration testing without
57 // relying on real ALTS handshaker service inside GCE.
58 // It is thread-safe.
59 class FakeHandshakerService : public HandshakerService::Service {
60  public:
FakeHandshakerService(const std::string & peer_identity)61   explicit FakeHandshakerService(const std::string& peer_identity)
62       : peer_identity_(peer_identity) {}
63 
DoHandshake(ServerContext *,ServerReaderWriter<HandshakerResp,HandshakerReq> * stream)64   Status DoHandshake(
65       ServerContext* /*server_context*/,
66       ServerReaderWriter<HandshakerResp, HandshakerReq>* stream) override {
67     Status status;
68     HandshakerContext context;
69     HandshakerReq request;
70     HandshakerResp response;
71     gpr_log(GPR_DEBUG, "Start a new handshake.");
72     while (stream->Read(&request)) {
73       status = ProcessRequest(&context, request, &response);
74       if (!status.ok()) return WriteErrorResponse(stream, status);
75       stream->Write(response);
76       if (context.state == COMPLETED) return Status::OK;
77       request.Clear();
78     }
79     return Status::OK;
80   }
81 
82  private:
83   // HandshakeState is used by fake handshaker server to keep track of client's
84   // handshake status. In the beginning of a handshake, the state is INITIAL.
85   // If start_client or start_server request is called, the state becomes at
86   // least STARTED. When the handshaker server produces the first fame, the
87   // state becomes SENT. After the handshaker server processes the final frame
88   // from the peer, the state becomes COMPLETED.
89   enum HandshakeState { INITIAL, STARTED, SENT, COMPLETED };
90 
91   struct HandshakerContext {
92     bool is_client = true;
93     HandshakeState state = INITIAL;
94   };
95 
ProcessRequest(HandshakerContext * context,const HandshakerReq & request,HandshakerResp * response)96   Status ProcessRequest(HandshakerContext* context,
97                         const HandshakerReq& request,
98                         HandshakerResp* response) {
99     GPR_ASSERT(context != nullptr && response != nullptr);
100     response->Clear();
101     if (request.has_client_start()) {
102       gpr_log(GPR_DEBUG, "Process client start request.");
103       return ProcessClientStart(context, request.client_start(), response);
104     } else if (request.has_server_start()) {
105       gpr_log(GPR_DEBUG, "Process server start request.");
106       return ProcessServerStart(context, request.server_start(), response);
107     } else if (request.has_next()) {
108       gpr_log(GPR_DEBUG, "Process next request.");
109       return ProcessNext(context, request.next(), response);
110     }
111     return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
112   }
113 
ProcessClientStart(HandshakerContext * context,const StartClientHandshakeReq & request,HandshakerResp * response)114   Status ProcessClientStart(HandshakerContext* context,
115                             const StartClientHandshakeReq& request,
116                             HandshakerResp* response) {
117     GPR_ASSERT(context != nullptr && response != nullptr);
118     // Checks request.
119     if (context->state != INITIAL) {
120       return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
121     }
122     if (request.application_protocols_size() == 0) {
123       return Status(StatusCode::INVALID_ARGUMENT,
124                     "At least one application protocol needed.");
125     }
126     if (request.record_protocols_size() == 0) {
127       return Status(StatusCode::INVALID_ARGUMENT,
128                     "At least one record protocol needed.");
129     }
130     // Sets response.
131     response->set_out_frames(kClientInitFrame);
132     response->set_bytes_consumed(0);
133     response->mutable_status()->set_code(StatusCode::OK);
134     // Updates handshaker context.
135     context->is_client = true;
136     context->state = SENT;
137     return Status::OK;
138   }
139 
ProcessServerStart(HandshakerContext * context,const StartServerHandshakeReq & request,HandshakerResp * response)140   Status ProcessServerStart(HandshakerContext* context,
141                             const StartServerHandshakeReq& request,
142                             HandshakerResp* response) {
143     GPR_ASSERT(context != nullptr && response != nullptr);
144     // Checks request.
145     if (context->state != INITIAL) {
146       return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
147     }
148     if (request.application_protocols_size() == 0) {
149       return Status(StatusCode::INVALID_ARGUMENT,
150                     "At least one application protocol needed.");
151     }
152     if (request.handshake_parameters().empty()) {
153       return Status(StatusCode::INVALID_ARGUMENT,
154                     "At least one set of handshake parameters needed.");
155     }
156     // Sets response.
157     if (request.in_bytes().empty()) {
158       // start_server request does not have in_bytes.
159       response->set_bytes_consumed(0);
160       context->state = STARTED;
161     } else {
162       // start_server request has in_bytes.
163       if (request.in_bytes() == kClientInitFrame) {
164         response->set_out_frames(kServerFrame);
165         response->set_bytes_consumed(strlen(kClientInitFrame));
166         context->state = SENT;
167       } else {
168         return Status(StatusCode::UNKNOWN, kInvalidFrameError);
169       }
170     }
171     response->mutable_status()->set_code(StatusCode::OK);
172     context->is_client = false;
173     return Status::OK;
174   }
175 
ProcessNext(HandshakerContext * context,const NextHandshakeMessageReq & request,HandshakerResp * response)176   Status ProcessNext(HandshakerContext* context,
177                      const NextHandshakeMessageReq& request,
178                      HandshakerResp* response) {
179     GPR_ASSERT(context != nullptr && response != nullptr);
180     if (context->is_client) {
181       // Processes next request on client side.
182       if (context->state != SENT) {
183         return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
184       }
185       if (request.in_bytes() != kServerFrame) {
186         return Status(StatusCode::UNKNOWN, kInvalidFrameError);
187       }
188       response->set_out_frames(kClientFinishFrame);
189       response->set_bytes_consumed(strlen(kServerFrame));
190       context->state = COMPLETED;
191     } else {
192       // Processes next request on server side.
193       HandshakeState current_state = context->state;
194       if (current_state == STARTED) {
195         if (request.in_bytes() != kClientInitFrame) {
196           return Status(StatusCode::UNKNOWN, kInvalidFrameError);
197         }
198         response->set_out_frames(kServerFrame);
199         response->set_bytes_consumed(strlen(kClientInitFrame));
200         context->state = SENT;
201       } else if (current_state == SENT) {
202         // Client finish frame may be sent along with the first payload from the
203         // client, handshaker only consumes the client finish frame.
204         if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
205             kClientFinishFrame) {
206           return Status(StatusCode::UNKNOWN, kInvalidFrameError);
207         }
208         response->set_bytes_consumed(strlen(kClientFinishFrame));
209         context->state = COMPLETED;
210       } else {
211         return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
212       }
213     }
214     // At this point, processing next request succeeded.
215     response->mutable_status()->set_code(StatusCode::OK);
216     if (context->state == COMPLETED) {
217       *response->mutable_result() = GetHandshakerResult();
218     }
219     return Status::OK;
220   }
221 
WriteErrorResponse(ServerReaderWriter<HandshakerResp,HandshakerReq> * stream,const Status & status)222   Status WriteErrorResponse(
223       ServerReaderWriter<HandshakerResp, HandshakerReq>* stream,
224       const Status& status) {
225     GPR_ASSERT(!status.ok());
226     HandshakerResp response;
227     response.mutable_status()->set_code(status.error_code());
228     response.mutable_status()->set_details(status.error_message());
229     stream->Write(response);
230     return status;
231   }
232 
GetHandshakerResult()233   HandshakerResult GetHandshakerResult() {
234     HandshakerResult result;
235     result.set_application_protocol("grpc");
236     result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
237     result.mutable_peer_identity()->set_service_account(peer_identity_);
238     result.mutable_local_identity()->set_service_account("local_identity");
239     string key(1024, '\0');
240     result.set_key_data(key);
241     result.set_max_frame_size(16384);
242     result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
243     result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
244     result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
245     result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
246     return result;
247   }
248 
249   const std::string peer_identity_;
250 };
251 
CreateFakeHandshakerService(const std::string & peer_identity)252 std::unique_ptr<grpc::Service> CreateFakeHandshakerService(
253     const std::string& peer_identity) {
254   return std::unique_ptr<grpc::Service>{
255       new grpc::gcp::FakeHandshakerService(peer_identity)};
256 }
257 
258 }  // namespace gcp
259 }  // namespace grpc
260