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 
19 #include <grpc/support/port_platform.h>
20 
21 #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
22 
23 #include <grpc/byte_buffer.h>
24 #include <grpc/support/alloc.h>
25 #include <grpc/support/log.h>
26 
27 #include "src/core/lib/slice/slice_internal.h"
28 #include "src/core/lib/surface/call.h"
29 #include "src/core/lib/surface/channel.h"
30 #include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h"
31 #include "src/core/tsi/alts/handshaker/alts_shared_resource.h"
32 #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h"
33 #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
34 
35 #define TSI_ALTS_INITIAL_BUFFER_SIZE 256
36 
37 const int kHandshakerClientOpNum = 4;
38 
39 struct alts_handshaker_client {
40   const alts_handshaker_client_vtable* vtable;
41 };
42 
43 typedef struct alts_grpc_handshaker_client {
44   alts_handshaker_client base;
45   alts_tsi_handshaker* handshaker;
46   grpc_call* call;
47   /* A pointer to a function handling the interaction with handshaker service.
48    * That is, it points to grpc_call_start_batch_and_execute when the handshaker
49    * client is used in a non-testing use case and points to a custom function
50    * that validates the data to be sent to handshaker service in a testing use
51    * case. */
52   alts_grpc_caller grpc_caller;
53   /* A callback function provided by gRPC to handle the response returned from
54    * handshaker service. It also serves to bring the control safely back to
55    * application when dedicated CQ and thread are used. */
56   grpc_iomgr_cb_func grpc_cb;
57   /* A gRPC closure to be scheduled when the response from handshaker service
58    * is received. It will be initialized with grpc_cb. */
59   grpc_closure on_handshaker_service_resp_recv;
60   /* Buffers containing information to be sent (or received) to (or from) the
61    * handshaker service. */
62   grpc_byte_buffer* send_buffer;
63   grpc_byte_buffer* recv_buffer;
64   grpc_status_code status;
65   /* Initial metadata to be received from handshaker service. */
66   grpc_metadata_array recv_initial_metadata;
67   /* A callback function provided by an application to be invoked when response
68    * is received from handshaker service. */
69   tsi_handshaker_on_next_done_cb cb;
70   void* user_data;
71   /* ALTS credential options passed in from the caller. */
72   grpc_alts_credentials_options* options;
73   /* target name information to be passed to handshaker service for server
74    * authorization check. */
75   grpc_slice target_name;
76   /* boolean flag indicating if the handshaker client is used at client
77    * (is_client = true) or server (is_client = false) side. */
78   bool is_client;
79   /* a temporary store for data received from handshaker service used to extract
80    * unused data. */
81   grpc_slice recv_bytes;
82   /* a buffer containing data to be sent to the grpc client or server's peer. */
83   unsigned char* buffer;
84   size_t buffer_size;
85 } alts_grpc_handshaker_client;
86 
handshaker_client_send_buffer_destroy(alts_grpc_handshaker_client * client)87 static void handshaker_client_send_buffer_destroy(
88     alts_grpc_handshaker_client* client) {
89   GPR_ASSERT(client != nullptr);
90   grpc_byte_buffer_destroy(client->send_buffer);
91   client->send_buffer = nullptr;
92 }
93 
is_handshake_finished_properly(grpc_gcp_handshaker_resp * resp)94 static bool is_handshake_finished_properly(grpc_gcp_handshaker_resp* resp) {
95   GPR_ASSERT(resp != nullptr);
96   if (resp->has_result) {
97     return true;
98   }
99   return false;
100 }
101 
alts_handshaker_client_handle_response(alts_handshaker_client * c,bool is_ok)102 void alts_handshaker_client_handle_response(alts_handshaker_client* c,
103                                             bool is_ok) {
104   GPR_ASSERT(c != nullptr);
105   alts_grpc_handshaker_client* client =
106       reinterpret_cast<alts_grpc_handshaker_client*>(c);
107   grpc_byte_buffer* recv_buffer = client->recv_buffer;
108   grpc_status_code status = client->status;
109   tsi_handshaker_on_next_done_cb cb = client->cb;
110   void* user_data = client->user_data;
111   alts_tsi_handshaker* handshaker = client->handshaker;
112 
113   /* Invalid input check. */
114   if (cb == nullptr) {
115     gpr_log(GPR_ERROR,
116             "cb is nullptr in alts_tsi_handshaker_handle_response()");
117     return;
118   }
119   if (handshaker == nullptr) {
120     gpr_log(GPR_ERROR,
121             "handshaker is nullptr in alts_tsi_handshaker_handle_response()");
122     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
123     return;
124   }
125   /* TSI handshake has been shutdown. */
126   if (alts_tsi_handshaker_has_shutdown(handshaker)) {
127     gpr_log(GPR_ERROR, "TSI handshake shutdown");
128     cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr);
129     return;
130   }
131   /* Failed grpc call check. */
132   if (!is_ok || status != GRPC_STATUS_OK) {
133     gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
134     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
135     return;
136   }
137   if (recv_buffer == nullptr) {
138     gpr_log(GPR_ERROR,
139             "recv_buffer is nullptr in alts_tsi_handshaker_handle_response()");
140     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
141     return;
142   }
143   grpc_gcp_handshaker_resp* resp =
144       alts_tsi_utils_deserialize_response(recv_buffer);
145   grpc_byte_buffer_destroy(client->recv_buffer);
146   client->recv_buffer = nullptr;
147   /* Invalid handshaker response check. */
148   if (resp == nullptr) {
149     gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed");
150     cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr);
151     return;
152   }
153   grpc_slice* slice = static_cast<grpc_slice*>(resp->out_frames.arg);
154   unsigned char* bytes_to_send = nullptr;
155   size_t bytes_to_send_size = 0;
156   if (slice != nullptr) {
157     bytes_to_send_size = GRPC_SLICE_LENGTH(*slice);
158     while (bytes_to_send_size > client->buffer_size) {
159       client->buffer_size *= 2;
160       client->buffer = static_cast<unsigned char*>(
161           gpr_realloc(client->buffer, client->buffer_size));
162     }
163     memcpy(client->buffer, GRPC_SLICE_START_PTR(*slice), bytes_to_send_size);
164     bytes_to_send = client->buffer;
165   }
166   tsi_handshaker_result* result = nullptr;
167   if (is_handshake_finished_properly(resp)) {
168     alts_tsi_handshaker_result_create(resp, client->is_client, &result);
169     alts_tsi_handshaker_result_set_unused_bytes(result, &client->recv_bytes,
170                                                 resp->bytes_consumed);
171   }
172   grpc_status_code code = static_cast<grpc_status_code>(resp->status.code);
173   if (code != GRPC_STATUS_OK) {
174     grpc_slice* details = static_cast<grpc_slice*>(resp->status.details.arg);
175     if (details != nullptr) {
176       char* error_details = grpc_slice_to_c_string(*details);
177       gpr_log(GPR_ERROR, "Error from handshaker service:%s", error_details);
178       gpr_free(error_details);
179     }
180   }
181   grpc_gcp_handshaker_resp_destroy(resp);
182   cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send,
183      bytes_to_send_size, result);
184 }
185 
186 /**
187  * Populate grpc operation data with the fields of ALTS handshaker client and
188  * make a grpc call.
189  */
make_grpc_call(alts_handshaker_client * c,bool is_start)190 static tsi_result make_grpc_call(alts_handshaker_client* c, bool is_start) {
191   GPR_ASSERT(c != nullptr);
192   alts_grpc_handshaker_client* client =
193       reinterpret_cast<alts_grpc_handshaker_client*>(c);
194   grpc_op ops[kHandshakerClientOpNum];
195   memset(ops, 0, sizeof(ops));
196   grpc_op* op = ops;
197   if (is_start) {
198     op->op = GRPC_OP_SEND_INITIAL_METADATA;
199     op->data.send_initial_metadata.count = 0;
200     op++;
201     GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
202     op->op = GRPC_OP_RECV_INITIAL_METADATA;
203     op->data.recv_initial_metadata.recv_initial_metadata =
204         &client->recv_initial_metadata;
205     op++;
206     GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
207   }
208   op->op = GRPC_OP_SEND_MESSAGE;
209   op->data.send_message.send_message = client->send_buffer;
210   op++;
211   GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
212   op->op = GRPC_OP_RECV_MESSAGE;
213   op->data.recv_message.recv_message = &client->recv_buffer;
214   op++;
215   GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
216   GPR_ASSERT(client->grpc_caller != nullptr);
217   if (client->grpc_caller(client->call, ops, static_cast<size_t>(op - ops),
218                           &client->on_handshaker_service_resp_recv) !=
219       GRPC_CALL_OK) {
220     gpr_log(GPR_ERROR, "Start batch operation failed");
221     return TSI_INTERNAL_ERROR;
222   }
223   return TSI_OK;
224 }
225 
226 /* Create and populate a client_start handshaker request, then serialize it. */
get_serialized_start_client(alts_handshaker_client * c)227 static grpc_byte_buffer* get_serialized_start_client(
228     alts_handshaker_client* c) {
229   GPR_ASSERT(c != nullptr);
230   alts_grpc_handshaker_client* client =
231       reinterpret_cast<alts_grpc_handshaker_client*>(c);
232   bool ok = true;
233   grpc_gcp_handshaker_req* req =
234       grpc_gcp_handshaker_req_create(CLIENT_START_REQ);
235   ok &= grpc_gcp_handshaker_req_set_handshake_protocol(
236       req, grpc_gcp_HandshakeProtocol_ALTS);
237   ok &= grpc_gcp_handshaker_req_add_application_protocol(
238       req, ALTS_APPLICATION_PROTOCOL);
239   ok &= grpc_gcp_handshaker_req_add_record_protocol(req, ALTS_RECORD_PROTOCOL);
240   grpc_gcp_rpc_protocol_versions* versions = &client->options->rpc_versions;
241   ok &= grpc_gcp_handshaker_req_set_rpc_versions(
242       req, versions->max_rpc_version.major, versions->max_rpc_version.minor,
243       versions->min_rpc_version.major, versions->min_rpc_version.minor);
244   char* target_name = grpc_slice_to_c_string(client->target_name);
245   ok &= grpc_gcp_handshaker_req_set_target_name(req, target_name);
246   target_service_account* ptr =
247       (reinterpret_cast<grpc_alts_credentials_client_options*>(client->options))
248           ->target_account_list_head;
249   while (ptr != nullptr) {
250     grpc_gcp_handshaker_req_add_target_identity_service_account(req, ptr->data);
251     ptr = ptr->next;
252   }
253   grpc_slice slice;
254   ok &= grpc_gcp_handshaker_req_encode(req, &slice);
255   grpc_byte_buffer* buffer = nullptr;
256   if (ok) {
257     buffer = grpc_raw_byte_buffer_create(&slice, 1 /* number of slices */);
258   }
259   grpc_slice_unref_internal(slice);
260   gpr_free(target_name);
261   grpc_gcp_handshaker_req_destroy(req);
262   return buffer;
263 }
264 
handshaker_client_start_client(alts_handshaker_client * c)265 static tsi_result handshaker_client_start_client(alts_handshaker_client* c) {
266   if (c == nullptr) {
267     gpr_log(GPR_ERROR, "client is nullptr in handshaker_client_start_client()");
268     return TSI_INVALID_ARGUMENT;
269   }
270   grpc_byte_buffer* buffer = get_serialized_start_client(c);
271   alts_grpc_handshaker_client* client =
272       reinterpret_cast<alts_grpc_handshaker_client*>(c);
273   if (buffer == nullptr) {
274     gpr_log(GPR_ERROR, "get_serialized_start_client() failed");
275     return TSI_INTERNAL_ERROR;
276   }
277   handshaker_client_send_buffer_destroy(client);
278   client->send_buffer = buffer;
279   tsi_result result = make_grpc_call(&client->base, true /* is_start */);
280   if (result != TSI_OK) {
281     gpr_log(GPR_ERROR, "make_grpc_call() failed");
282   }
283   return result;
284 }
285 
286 /* Create and populate a start_server handshaker request, then serialize it. */
get_serialized_start_server(alts_handshaker_client * c,grpc_slice * bytes_received)287 static grpc_byte_buffer* get_serialized_start_server(
288     alts_handshaker_client* c, grpc_slice* bytes_received) {
289   GPR_ASSERT(c != nullptr);
290   GPR_ASSERT(bytes_received != nullptr);
291   alts_grpc_handshaker_client* client =
292       reinterpret_cast<alts_grpc_handshaker_client*>(c);
293   grpc_gcp_handshaker_req* req =
294       grpc_gcp_handshaker_req_create(SERVER_START_REQ);
295   bool ok = grpc_gcp_handshaker_req_add_application_protocol(
296       req, ALTS_APPLICATION_PROTOCOL);
297   ok &= grpc_gcp_handshaker_req_param_add_record_protocol(
298       req, grpc_gcp_HandshakeProtocol_ALTS, ALTS_RECORD_PROTOCOL);
299   ok &= grpc_gcp_handshaker_req_set_in_bytes(
300       req, reinterpret_cast<const char*> GRPC_SLICE_START_PTR(*bytes_received),
301       GRPC_SLICE_LENGTH(*bytes_received));
302   grpc_gcp_rpc_protocol_versions* versions = &client->options->rpc_versions;
303   ok &= grpc_gcp_handshaker_req_set_rpc_versions(
304       req, versions->max_rpc_version.major, versions->max_rpc_version.minor,
305       versions->min_rpc_version.major, versions->min_rpc_version.minor);
306   grpc_slice req_slice;
307   ok &= grpc_gcp_handshaker_req_encode(req, &req_slice);
308   grpc_byte_buffer* buffer = nullptr;
309   if (ok) {
310     buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */);
311   }
312   grpc_slice_unref_internal(req_slice);
313   grpc_gcp_handshaker_req_destroy(req);
314   return buffer;
315 }
316 
handshaker_client_start_server(alts_handshaker_client * c,grpc_slice * bytes_received)317 static tsi_result handshaker_client_start_server(alts_handshaker_client* c,
318                                                  grpc_slice* bytes_received) {
319   if (c == nullptr || bytes_received == nullptr) {
320     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_server()");
321     return TSI_INVALID_ARGUMENT;
322   }
323   alts_grpc_handshaker_client* client =
324       reinterpret_cast<alts_grpc_handshaker_client*>(c);
325   grpc_byte_buffer* buffer = get_serialized_start_server(c, bytes_received);
326   if (buffer == nullptr) {
327     gpr_log(GPR_ERROR, "get_serialized_start_server() failed");
328     return TSI_INTERNAL_ERROR;
329   }
330   handshaker_client_send_buffer_destroy(client);
331   client->send_buffer = buffer;
332   tsi_result result = make_grpc_call(&client->base, true /* is_start */);
333   if (result != TSI_OK) {
334     gpr_log(GPR_ERROR, "make_grpc_call() failed");
335   }
336   return result;
337 }
338 
339 /* Create and populate a next handshaker request, then serialize it. */
get_serialized_next(grpc_slice * bytes_received)340 static grpc_byte_buffer* get_serialized_next(grpc_slice* bytes_received) {
341   GPR_ASSERT(bytes_received != nullptr);
342   grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_req_create(NEXT_REQ);
343   bool ok = grpc_gcp_handshaker_req_set_in_bytes(
344       req, reinterpret_cast<const char*> GRPC_SLICE_START_PTR(*bytes_received),
345       GRPC_SLICE_LENGTH(*bytes_received));
346   grpc_slice req_slice;
347   ok &= grpc_gcp_handshaker_req_encode(req, &req_slice);
348   grpc_byte_buffer* buffer = nullptr;
349   if (ok) {
350     buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */);
351   }
352   grpc_slice_unref_internal(req_slice);
353   grpc_gcp_handshaker_req_destroy(req);
354   return buffer;
355 }
356 
handshaker_client_next(alts_handshaker_client * c,grpc_slice * bytes_received)357 static tsi_result handshaker_client_next(alts_handshaker_client* c,
358                                          grpc_slice* bytes_received) {
359   if (c == nullptr || bytes_received == nullptr) {
360     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_next()");
361     return TSI_INVALID_ARGUMENT;
362   }
363   alts_grpc_handshaker_client* client =
364       reinterpret_cast<alts_grpc_handshaker_client*>(c);
365   grpc_slice_unref_internal(client->recv_bytes);
366   client->recv_bytes = grpc_slice_ref_internal(*bytes_received);
367   grpc_byte_buffer* buffer = get_serialized_next(bytes_received);
368   if (buffer == nullptr) {
369     gpr_log(GPR_ERROR, "get_serialized_next() failed");
370     return TSI_INTERNAL_ERROR;
371   }
372   handshaker_client_send_buffer_destroy(client);
373   client->send_buffer = buffer;
374   tsi_result result = make_grpc_call(&client->base, false /* is_start */);
375   if (result != TSI_OK) {
376     gpr_log(GPR_ERROR, "make_grpc_call() failed");
377   }
378   return result;
379 }
380 
handshaker_client_shutdown(alts_handshaker_client * c)381 static void handshaker_client_shutdown(alts_handshaker_client* c) {
382   GPR_ASSERT(c != nullptr);
383   alts_grpc_handshaker_client* client =
384       reinterpret_cast<alts_grpc_handshaker_client*>(c);
385   if (client->call != nullptr) {
386     grpc_call_cancel_internal(client->call);
387   }
388 }
389 
handshaker_client_destruct(alts_handshaker_client * c)390 static void handshaker_client_destruct(alts_handshaker_client* c) {
391   if (c == nullptr) {
392     return;
393   }
394   alts_grpc_handshaker_client* client =
395       reinterpret_cast<alts_grpc_handshaker_client*>(c);
396   if (client->call != nullptr) {
397     grpc_call_unref(client->call);
398   }
399 }
400 
401 static const alts_handshaker_client_vtable vtable = {
402     handshaker_client_start_client, handshaker_client_start_server,
403     handshaker_client_next, handshaker_client_shutdown,
404     handshaker_client_destruct};
405 
alts_grpc_handshaker_client_create(alts_tsi_handshaker * handshaker,grpc_channel * channel,const char * handshaker_service_url,grpc_pollset_set * interested_parties,grpc_alts_credentials_options * options,const grpc_slice & target_name,grpc_iomgr_cb_func grpc_cb,tsi_handshaker_on_next_done_cb cb,void * user_data,alts_handshaker_client_vtable * vtable_for_testing,bool is_client)406 alts_handshaker_client* alts_grpc_handshaker_client_create(
407     alts_tsi_handshaker* handshaker, grpc_channel* channel,
408     const char* handshaker_service_url, grpc_pollset_set* interested_parties,
409     grpc_alts_credentials_options* options, const grpc_slice& target_name,
410     grpc_iomgr_cb_func grpc_cb, tsi_handshaker_on_next_done_cb cb,
411     void* user_data, alts_handshaker_client_vtable* vtable_for_testing,
412     bool is_client) {
413   if (channel == nullptr || handshaker_service_url == nullptr) {
414     gpr_log(GPR_ERROR, "Invalid arguments to alts_handshaker_client_create()");
415     return nullptr;
416   }
417   alts_grpc_handshaker_client* client =
418       static_cast<alts_grpc_handshaker_client*>(gpr_zalloc(sizeof(*client)));
419   client->grpc_caller = grpc_call_start_batch_and_execute;
420   client->handshaker = handshaker;
421   client->cb = cb;
422   client->user_data = user_data;
423   client->send_buffer = nullptr;
424   client->recv_buffer = nullptr;
425   client->options = grpc_alts_credentials_options_copy(options);
426   client->target_name = grpc_slice_copy(target_name);
427   client->recv_bytes = grpc_empty_slice();
428   grpc_metadata_array_init(&client->recv_initial_metadata);
429   client->grpc_cb = grpc_cb;
430   client->is_client = is_client;
431   client->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE;
432   client->buffer = static_cast<unsigned char*>(gpr_zalloc(client->buffer_size));
433   grpc_slice slice = grpc_slice_from_copied_string(handshaker_service_url);
434   client->call =
435       strcmp(handshaker_service_url, ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING) ==
436               0
437           ? nullptr
438           : grpc_channel_create_pollset_set_call(
439                 channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties,
440                 grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice,
441                 GRPC_MILLIS_INF_FUTURE, nullptr);
442   client->base.vtable =
443       vtable_for_testing == nullptr ? &vtable : vtable_for_testing;
444   GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, client->grpc_cb,
445                     client, grpc_schedule_on_exec_ctx);
446   grpc_slice_unref_internal(slice);
447   return &client->base;
448 }
449 
450 namespace grpc_core {
451 namespace internal {
452 
alts_handshaker_client_set_grpc_caller_for_testing(alts_handshaker_client * c,alts_grpc_caller caller)453 void alts_handshaker_client_set_grpc_caller_for_testing(
454     alts_handshaker_client* c, alts_grpc_caller caller) {
455   GPR_ASSERT(c != nullptr && caller != nullptr);
456   alts_grpc_handshaker_client* client =
457       reinterpret_cast<alts_grpc_handshaker_client*>(c);
458   client->grpc_caller = caller;
459 }
460 
alts_handshaker_client_get_send_buffer_for_testing(alts_handshaker_client * c)461 grpc_byte_buffer* alts_handshaker_client_get_send_buffer_for_testing(
462     alts_handshaker_client* c) {
463   GPR_ASSERT(c != nullptr);
464   alts_grpc_handshaker_client* client =
465       reinterpret_cast<alts_grpc_handshaker_client*>(c);
466   return client->send_buffer;
467 }
468 
alts_handshaker_client_get_recv_buffer_addr_for_testing(alts_handshaker_client * c)469 grpc_byte_buffer** alts_handshaker_client_get_recv_buffer_addr_for_testing(
470     alts_handshaker_client* c) {
471   GPR_ASSERT(c != nullptr);
472   alts_grpc_handshaker_client* client =
473       reinterpret_cast<alts_grpc_handshaker_client*>(c);
474   return &client->recv_buffer;
475 }
476 
alts_handshaker_client_get_initial_metadata_for_testing(alts_handshaker_client * c)477 grpc_metadata_array* alts_handshaker_client_get_initial_metadata_for_testing(
478     alts_handshaker_client* c) {
479   GPR_ASSERT(c != nullptr);
480   alts_grpc_handshaker_client* client =
481       reinterpret_cast<alts_grpc_handshaker_client*>(c);
482   return &client->recv_initial_metadata;
483 }
484 
alts_handshaker_client_set_recv_bytes_for_testing(alts_handshaker_client * c,grpc_slice * recv_bytes)485 void alts_handshaker_client_set_recv_bytes_for_testing(
486     alts_handshaker_client* c, grpc_slice* recv_bytes) {
487   GPR_ASSERT(c != nullptr);
488   alts_grpc_handshaker_client* client =
489       reinterpret_cast<alts_grpc_handshaker_client*>(c);
490   client->recv_bytes = grpc_slice_ref_internal(*recv_bytes);
491 }
492 
alts_handshaker_client_set_fields_for_testing(alts_handshaker_client * c,alts_tsi_handshaker * handshaker,tsi_handshaker_on_next_done_cb cb,void * user_data,grpc_byte_buffer * recv_buffer,grpc_status_code status)493 void alts_handshaker_client_set_fields_for_testing(
494     alts_handshaker_client* c, alts_tsi_handshaker* handshaker,
495     tsi_handshaker_on_next_done_cb cb, void* user_data,
496     grpc_byte_buffer* recv_buffer, grpc_status_code status) {
497   GPR_ASSERT(c != nullptr);
498   alts_grpc_handshaker_client* client =
499       reinterpret_cast<alts_grpc_handshaker_client*>(c);
500   client->handshaker = handshaker;
501   client->cb = cb;
502   client->user_data = user_data;
503   client->recv_buffer = recv_buffer;
504   client->status = status;
505 }
506 
alts_handshaker_client_check_fields_for_testing(alts_handshaker_client * c,tsi_handshaker_on_next_done_cb cb,void * user_data,bool has_sent_start_message,grpc_slice * recv_bytes)507 void alts_handshaker_client_check_fields_for_testing(
508     alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb,
509     void* user_data, bool has_sent_start_message, grpc_slice* recv_bytes) {
510   GPR_ASSERT(c != nullptr);
511   alts_grpc_handshaker_client* client =
512       reinterpret_cast<alts_grpc_handshaker_client*>(c);
513   GPR_ASSERT(client->cb == cb);
514   GPR_ASSERT(client->user_data == user_data);
515   if (recv_bytes != nullptr) {
516     GPR_ASSERT(grpc_slice_cmp(client->recv_bytes, *recv_bytes) == 0);
517   }
518   GPR_ASSERT(alts_tsi_handshaker_get_has_sent_start_message_for_testing(
519                  client->handshaker) == has_sent_start_message);
520 }
521 
alts_handshaker_client_set_vtable_for_testing(alts_handshaker_client * c,alts_handshaker_client_vtable * vtable)522 void alts_handshaker_client_set_vtable_for_testing(
523     alts_handshaker_client* c, alts_handshaker_client_vtable* vtable) {
524   GPR_ASSERT(c != nullptr);
525   GPR_ASSERT(vtable != nullptr);
526   alts_grpc_handshaker_client* client =
527       reinterpret_cast<alts_grpc_handshaker_client*>(c);
528   client->base.vtable = vtable;
529 }
530 
alts_handshaker_client_get_handshaker_for_testing(alts_handshaker_client * c)531 alts_tsi_handshaker* alts_handshaker_client_get_handshaker_for_testing(
532     alts_handshaker_client* c) {
533   GPR_ASSERT(c != nullptr);
534   alts_grpc_handshaker_client* client =
535       reinterpret_cast<alts_grpc_handshaker_client*>(c);
536   return client->handshaker;
537 }
538 
alts_handshaker_client_set_cb_for_testing(alts_handshaker_client * c,tsi_handshaker_on_next_done_cb cb)539 void alts_handshaker_client_set_cb_for_testing(
540     alts_handshaker_client* c, tsi_handshaker_on_next_done_cb cb) {
541   GPR_ASSERT(c != nullptr);
542   alts_grpc_handshaker_client* client =
543       reinterpret_cast<alts_grpc_handshaker_client*>(c);
544   client->cb = cb;
545 }
546 
alts_handshaker_client_get_closure_for_testing(alts_handshaker_client * c)547 grpc_closure* alts_handshaker_client_get_closure_for_testing(
548     alts_handshaker_client* c) {
549   GPR_ASSERT(c != nullptr);
550   alts_grpc_handshaker_client* client =
551       reinterpret_cast<alts_grpc_handshaker_client*>(c);
552   return &client->on_handshaker_service_resp_recv;
553 }
554 
555 }  // namespace internal
556 }  // namespace grpc_core
557 
alts_handshaker_client_start_client(alts_handshaker_client * client)558 tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client) {
559   if (client != nullptr && client->vtable != nullptr &&
560       client->vtable->client_start != nullptr) {
561     return client->vtable->client_start(client);
562   }
563   gpr_log(GPR_ERROR,
564           "client or client->vtable has not been initialized properly");
565   return TSI_INVALID_ARGUMENT;
566 }
567 
alts_handshaker_client_start_server(alts_handshaker_client * client,grpc_slice * bytes_received)568 tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client,
569                                                grpc_slice* bytes_received) {
570   if (client != nullptr && client->vtable != nullptr &&
571       client->vtable->server_start != nullptr) {
572     return client->vtable->server_start(client, bytes_received);
573   }
574   gpr_log(GPR_ERROR,
575           "client or client->vtable has not been initialized properly");
576   return TSI_INVALID_ARGUMENT;
577 }
578 
alts_handshaker_client_next(alts_handshaker_client * client,grpc_slice * bytes_received)579 tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
580                                        grpc_slice* bytes_received) {
581   if (client != nullptr && client->vtable != nullptr &&
582       client->vtable->next != nullptr) {
583     return client->vtable->next(client, bytes_received);
584   }
585   gpr_log(GPR_ERROR,
586           "client or client->vtable has not been initialized properly");
587   return TSI_INVALID_ARGUMENT;
588 }
589 
alts_handshaker_client_shutdown(alts_handshaker_client * client)590 void alts_handshaker_client_shutdown(alts_handshaker_client* client) {
591   if (client != nullptr && client->vtable != nullptr &&
592       client->vtable->shutdown != nullptr) {
593     client->vtable->shutdown(client);
594   }
595 }
596 
alts_handshaker_client_destroy(alts_handshaker_client * c)597 void alts_handshaker_client_destroy(alts_handshaker_client* c) {
598   if (c != nullptr) {
599     if (c->vtable != nullptr && c->vtable->destruct != nullptr) {
600       c->vtable->destruct(c);
601     }
602     alts_grpc_handshaker_client* client =
603         reinterpret_cast<alts_grpc_handshaker_client*>(c);
604     grpc_byte_buffer_destroy(client->send_buffer);
605     grpc_byte_buffer_destroy(client->recv_buffer);
606     client->send_buffer = nullptr;
607     client->recv_buffer = nullptr;
608     grpc_metadata_array_destroy(&client->recv_initial_metadata);
609     grpc_slice_unref_internal(client->recv_bytes);
610     grpc_slice_unref_internal(client->target_name);
611     grpc_alts_credentials_options_destroy(client->options);
612     gpr_free(client->buffer);
613     gpr_free(client);
614   }
615 }
616