• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/grpc.h>
20 
21 #include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
22 #include "src/core/tsi/alts/handshaker/alts_tsi_event.h"
23 #include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
24 #include "src/core/tsi/transport_security.h"
25 #include "src/core/tsi/transport_security_interface.h"
26 #include "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h"
27 
28 #define ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME "Hello Google"
29 #define ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL "lame"
30 #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME "bigtable.google.api.com"
31 #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1 "A@google.com"
32 #define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2 "B@google.com"
33 
34 const size_t kHandshakerClientOpNum = 4;
35 const size_t kMaxRpcVersionMajor = 3;
36 const size_t kMaxRpcVersionMinor = 2;
37 const size_t kMinRpcVersionMajor = 2;
38 const size_t kMinRpcVersionMinor = 1;
39 
40 using grpc_core::internal::alts_handshaker_client_set_grpc_caller_for_testing;
41 
42 typedef struct alts_handshaker_client_test_config {
43   grpc_channel* channel;
44   grpc_completion_queue* cq;
45   alts_handshaker_client* client;
46   grpc_slice out_frame;
47 } alts_handshaker_client_test_config;
48 
alts_tsi_event_create_for_testing(bool is_client)49 static alts_tsi_event* alts_tsi_event_create_for_testing(bool is_client) {
50   alts_tsi_event* e = static_cast<alts_tsi_event*>(gpr_zalloc(sizeof(*e)));
51   grpc_metadata_array_init(&e->initial_metadata);
52   grpc_metadata_array_init(&e->trailing_metadata);
53   e->options = is_client ? grpc_alts_credentials_client_options_create()
54                          : grpc_alts_credentials_server_options_create();
55   if (is_client) {
56     grpc_alts_credentials_client_options_add_target_service_account(
57         e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1);
58     grpc_alts_credentials_client_options_add_target_service_account(
59         e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2);
60   }
61   grpc_gcp_rpc_protocol_versions* versions = &e->options->rpc_versions;
62   GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_max(
63       versions, kMaxRpcVersionMajor, kMaxRpcVersionMinor));
64   GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_min(
65       versions, kMinRpcVersionMajor, kMinRpcVersionMinor));
66   e->target_name =
67       grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME);
68   return e;
69 }
70 
validate_rpc_protocol_versions(grpc_gcp_rpc_protocol_versions * versions)71 static void validate_rpc_protocol_versions(
72     grpc_gcp_rpc_protocol_versions* versions) {
73   GPR_ASSERT(versions != nullptr);
74   GPR_ASSERT(versions->max_rpc_version.major == kMaxRpcVersionMajor);
75   GPR_ASSERT(versions->max_rpc_version.minor == kMaxRpcVersionMinor);
76   GPR_ASSERT(versions->min_rpc_version.major == kMinRpcVersionMajor);
77   GPR_ASSERT(versions->min_rpc_version.minor == kMinRpcVersionMinor);
78 }
79 
validate_target_identities(const repeated_field * target_identity_head)80 static void validate_target_identities(
81     const repeated_field* target_identity_head) {
82   grpc_gcp_identity* target_identity1 = static_cast<grpc_gcp_identity*>(
83       const_cast<void*>(target_identity_head->next->data));
84   grpc_gcp_identity* target_identity2 = static_cast<grpc_gcp_identity*>(
85       const_cast<void*>(target_identity_head->data));
86   grpc_slice* service_account1 =
87       static_cast<grpc_slice*>(target_identity1->service_account.arg);
88   grpc_slice* service_account2 =
89       static_cast<grpc_slice*>(target_identity2->service_account.arg);
90   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*service_account1),
91                     ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1,
92                     GRPC_SLICE_LENGTH(*service_account1)) == 0);
93   GPR_ASSERT(strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1) ==
94              GRPC_SLICE_LENGTH(*service_account1));
95   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*service_account2),
96                     ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2,
97                     GRPC_SLICE_LENGTH(*service_account2)) == 0);
98   GPR_ASSERT(strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2) ==
99              GRPC_SLICE_LENGTH(*service_account2));
100 }
101 
102 /**
103  * Validate if grpc operation data is correctly populated with the fields of
104  * ALTS TSI event.
105  */
validate_op(alts_tsi_event * event,const grpc_op * op,size_t nops,bool is_start)106 static bool validate_op(alts_tsi_event* event, const grpc_op* op, size_t nops,
107                         bool is_start) {
108   GPR_ASSERT(event != nullptr && op != nullptr && nops != 0);
109   bool ok = true;
110   grpc_op* start_op = const_cast<grpc_op*>(op);
111   if (is_start) {
112     ok &= (op->op == GRPC_OP_SEND_INITIAL_METADATA);
113     ok &= (op->data.send_initial_metadata.count == 0);
114     op++;
115     GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
116 
117     ok &= (op->op == GRPC_OP_RECV_INITIAL_METADATA);
118     ok &= (op->data.recv_initial_metadata.recv_initial_metadata ==
119            &event->initial_metadata);
120     op++;
121     GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
122   }
123   ok &= (op->op == GRPC_OP_SEND_MESSAGE);
124   ok &= (op->data.send_message.send_message == event->send_buffer);
125   op++;
126   GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
127 
128   ok &= (op->op == GRPC_OP_RECV_MESSAGE);
129   ok &= (op->data.recv_message.recv_message == &event->recv_buffer);
130   op++;
131   GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
132 
133   return ok;
134 }
135 
deserialize_handshaker_req(grpc_gcp_handshaker_req_type type,grpc_byte_buffer * buffer)136 static grpc_gcp_handshaker_req* deserialize_handshaker_req(
137     grpc_gcp_handshaker_req_type type, grpc_byte_buffer* buffer) {
138   GPR_ASSERT(buffer != nullptr);
139   grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_decoded_req_create(type);
140   grpc_byte_buffer_reader bbr;
141   GPR_ASSERT(grpc_byte_buffer_reader_init(&bbr, buffer));
142   grpc_slice slice = grpc_byte_buffer_reader_readall(&bbr);
143   GPR_ASSERT(grpc_gcp_handshaker_req_decode(slice, req));
144   grpc_slice_unref(slice);
145   grpc_byte_buffer_reader_destroy(&bbr);
146   return req;
147 }
148 
149 /**
150  * A mock grpc_caller used to check if client_start, server_start, and next
151  * operations correctly handle invalid arguments. It should not be called.
152  */
check_must_not_be_called(grpc_call * call,const grpc_op * ops,size_t nops,void * tag)153 static grpc_call_error check_must_not_be_called(grpc_call* call,
154                                                 const grpc_op* ops, size_t nops,
155                                                 void* tag) {
156   GPR_ASSERT(0);
157 }
158 
159 /**
160  * A mock grpc_caller used to check correct execution of client_start operation.
161  * It checks if the client_start handshaker request is populated with correct
162  * handshake_security_protocol, application_protocol, and record_protocol, and
163  * op is correctly populated.
164  */
check_client_start_success(grpc_call * call,const grpc_op * op,size_t nops,void * tag)165 static grpc_call_error check_client_start_success(grpc_call* call,
166                                                   const grpc_op* op,
167                                                   size_t nops, void* tag) {
168   alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
169   grpc_gcp_handshaker_req* req =
170       deserialize_handshaker_req(CLIENT_START_REQ, event->send_buffer);
171   GPR_ASSERT(req->client_start.handshake_security_protocol ==
172              grpc_gcp_HandshakeProtocol_ALTS);
173   const void* data = (static_cast<repeated_field*>(
174                           req->client_start.application_protocols.arg))
175                          ->data;
176   GPR_ASSERT(data != nullptr);
177   grpc_slice* application_protocol = (grpc_slice*)data;
178   data = (static_cast<repeated_field*>(req->client_start.record_protocols.arg))
179              ->data;
180   grpc_slice* record_protocol = (grpc_slice*)data;
181   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*application_protocol),
182                     ALTS_APPLICATION_PROTOCOL,
183                     GRPC_SLICE_LENGTH(*application_protocol)) == 0);
184   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*record_protocol),
185                     ALTS_RECORD_PROTOCOL,
186                     GRPC_SLICE_LENGTH(*record_protocol)) == 0);
187   validate_rpc_protocol_versions(&req->client_start.rpc_versions);
188   validate_target_identities(
189       static_cast<repeated_field*>(req->client_start.target_identities.arg));
190   grpc_slice* target_name =
191       static_cast<grpc_slice*>(req->client_start.target_name.arg);
192   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*target_name),
193                     ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME,
194                     GRPC_SLICE_LENGTH(*target_name)) == 0);
195   GPR_ASSERT(GRPC_SLICE_LENGTH(*target_name) ==
196              strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME));
197   GPR_ASSERT(validate_op(event, op, nops, true /* is_start */));
198   grpc_gcp_handshaker_req_destroy(req);
199   return GRPC_CALL_OK;
200 }
201 
202 /**
203  * A mock grpc_caller used to check correct execution of server_start operation.
204  * It checks if the server_start handshaker request is populated with correct
205  * handshake_security_protocol, application_protocol, and record_protocol, and
206  * op is correctly populated.
207  */
check_server_start_success(grpc_call * call,const grpc_op * op,size_t nops,void * tag)208 static grpc_call_error check_server_start_success(grpc_call* call,
209                                                   const grpc_op* op,
210                                                   size_t nops, void* tag) {
211   alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
212   grpc_gcp_handshaker_req* req =
213       deserialize_handshaker_req(SERVER_START_REQ, event->send_buffer);
214   const void* data = (static_cast<repeated_field*>(
215                           req->server_start.application_protocols.arg))
216                          ->data;
217   GPR_ASSERT(data != nullptr);
218   grpc_slice* application_protocol = (grpc_slice*)data;
219   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*application_protocol),
220                     ALTS_APPLICATION_PROTOCOL,
221                     GRPC_SLICE_LENGTH(*application_protocol)) == 0);
222   GPR_ASSERT(req->server_start.handshake_parameters_count == 1);
223   GPR_ASSERT(req->server_start.handshake_parameters[0].key ==
224              grpc_gcp_HandshakeProtocol_ALTS);
225   data = (static_cast<repeated_field*>(req->server_start.handshake_parameters[0]
226                                            .value.record_protocols.arg))
227              ->data;
228   GPR_ASSERT(data != nullptr);
229   grpc_slice* record_protocol = (grpc_slice*)data;
230   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*record_protocol),
231                     ALTS_RECORD_PROTOCOL,
232                     GRPC_SLICE_LENGTH(*record_protocol)) == 0);
233   validate_rpc_protocol_versions(&req->server_start.rpc_versions);
234   GPR_ASSERT(validate_op(event, op, nops, true /* is_start */));
235   grpc_gcp_handshaker_req_destroy(req);
236   return GRPC_CALL_OK;
237 }
238 
239 /**
240  * A mock grpc_caller used to check correct execution of next operation. It
241  * checks if the next handshaker request is populated with correct information,
242  * and op is correctly populated.
243  */
check_next_success(grpc_call * call,const grpc_op * op,size_t nops,void * tag)244 static grpc_call_error check_next_success(grpc_call* call, const grpc_op* op,
245                                           size_t nops, void* tag) {
246   alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
247   grpc_gcp_handshaker_req* req =
248       deserialize_handshaker_req(NEXT_REQ, event->send_buffer);
249   grpc_slice* in_bytes = static_cast<grpc_slice*>(req->next.in_bytes.arg);
250   GPR_ASSERT(in_bytes != nullptr);
251   GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*in_bytes),
252                     ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME,
253                     GRPC_SLICE_LENGTH(*in_bytes)) == 0);
254   GPR_ASSERT(validate_op(event, op, nops, false /* is_start */));
255   grpc_gcp_handshaker_req_destroy(req);
256   return GRPC_CALL_OK;
257 }
258 /**
259  * A mock grpc_caller used to check if client_start, server_start, and next
260  * operations correctly handle the situation when the grpc call made to the
261  * handshaker service fails.
262  */
check_grpc_call_failure(grpc_call * call,const grpc_op * op,size_t nops,void * tag)263 static grpc_call_error check_grpc_call_failure(grpc_call* call,
264                                                const grpc_op* op, size_t nops,
265                                                void* tag) {
266   return GRPC_CALL_ERROR;
267 }
268 
create_config()269 static alts_handshaker_client_test_config* create_config() {
270   alts_handshaker_client_test_config* config =
271       static_cast<alts_handshaker_client_test_config*>(
272           gpr_zalloc(sizeof(*config)));
273   config->channel = grpc_insecure_channel_create(
274       ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL, nullptr, nullptr);
275   config->cq = grpc_completion_queue_create_for_next(nullptr);
276   config->client = alts_grpc_handshaker_client_create(
277       config->channel, config->cq,
278       ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL);
279   GPR_ASSERT(config->client != nullptr);
280   config->out_frame =
281       grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME);
282   return config;
283 }
284 
destroy_config(alts_handshaker_client_test_config * config)285 static void destroy_config(alts_handshaker_client_test_config* config) {
286   if (config == nullptr) {
287     return;
288   }
289   grpc_completion_queue_destroy(config->cq);
290   grpc_channel_destroy(config->channel);
291   alts_handshaker_client_destroy(config->client);
292   grpc_slice_unref(config->out_frame);
293   gpr_free(config);
294 }
295 
schedule_request_invalid_arg_test()296 static void schedule_request_invalid_arg_test() {
297   /* Initialization. */
298   alts_handshaker_client_test_config* config = create_config();
299   alts_tsi_event* event = nullptr;
300 
301   /* Tests. */
302   alts_handshaker_client_set_grpc_caller_for_testing(config->client,
303                                                      check_must_not_be_called);
304   event = alts_tsi_event_create_for_testing(true /* is_client */);
305   /* Check client_start. */
306   GPR_ASSERT(alts_handshaker_client_start_client(nullptr, event) ==
307              TSI_INVALID_ARGUMENT);
308   GPR_ASSERT(alts_handshaker_client_start_client(config->client, nullptr) ==
309              TSI_INVALID_ARGUMENT);
310 
311   /* Check server_start. */
312   GPR_ASSERT(alts_handshaker_client_start_server(
313                  config->client, event, nullptr) == TSI_INVALID_ARGUMENT);
314   GPR_ASSERT(alts_handshaker_client_start_server(config->client, nullptr,
315                                                  &config->out_frame) ==
316              TSI_INVALID_ARGUMENT);
317   GPR_ASSERT(alts_handshaker_client_start_server(
318                  nullptr, event, &config->out_frame) == TSI_INVALID_ARGUMENT);
319 
320   /* Check next. */
321   GPR_ASSERT(alts_handshaker_client_next(config->client, event, nullptr) ==
322              TSI_INVALID_ARGUMENT);
323   GPR_ASSERT(alts_handshaker_client_next(config->client, nullptr,
324                                          &config->out_frame) ==
325              TSI_INVALID_ARGUMENT);
326   GPR_ASSERT(alts_handshaker_client_next(nullptr, event, &config->out_frame) ==
327              TSI_INVALID_ARGUMENT);
328 
329   /* Check shutdown. */
330   alts_handshaker_client_shutdown(nullptr);
331 
332   /* Cleanup. */
333   alts_tsi_event_destroy(event);
334   destroy_config(config);
335 }
336 
schedule_request_success_test()337 static void schedule_request_success_test() {
338   /* Initialization. */
339   alts_handshaker_client_test_config* config = create_config();
340   alts_tsi_event* event = nullptr;
341 
342   /* Check client_start success. */
343   alts_handshaker_client_set_grpc_caller_for_testing(
344       config->client, check_client_start_success);
345   event = alts_tsi_event_create_for_testing(true /* is_client. */);
346   GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) ==
347              TSI_OK);
348   alts_tsi_event_destroy(event);
349 
350   /* Check server_start success. */
351   alts_handshaker_client_set_grpc_caller_for_testing(
352       config->client, check_server_start_success);
353   event = alts_tsi_event_create_for_testing(false /* is_client. */);
354   GPR_ASSERT(alts_handshaker_client_start_server(config->client, event,
355                                                  &config->out_frame) == TSI_OK);
356   alts_tsi_event_destroy(event);
357 
358   /* Check next success. */
359   alts_handshaker_client_set_grpc_caller_for_testing(config->client,
360                                                      check_next_success);
361   event = alts_tsi_event_create_for_testing(true /* is_client. */);
362   GPR_ASSERT(alts_handshaker_client_next(config->client, event,
363                                          &config->out_frame) == TSI_OK);
364   alts_tsi_event_destroy(event);
365 
366   /* Cleanup. */
367   destroy_config(config);
368 }
369 
schedule_request_grpc_call_failure_test()370 static void schedule_request_grpc_call_failure_test() {
371   /* Initialization. */
372   alts_handshaker_client_test_config* config = create_config();
373   alts_tsi_event* event = nullptr;
374 
375   /* Check client_start failure. */
376   alts_handshaker_client_set_grpc_caller_for_testing(config->client,
377                                                      check_grpc_call_failure);
378   event = alts_tsi_event_create_for_testing(true /* is_client. */);
379   GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) ==
380              TSI_INTERNAL_ERROR);
381   alts_tsi_event_destroy(event);
382 
383   /* Check server_start failure. */
384   event = alts_tsi_event_create_for_testing(false /* is_client. */);
385   GPR_ASSERT(alts_handshaker_client_start_server(config->client, event,
386                                                  &config->out_frame) ==
387              TSI_INTERNAL_ERROR);
388   alts_tsi_event_destroy(event);
389 
390   /* Check next failure. */
391   event = alts_tsi_event_create_for_testing(true /* is_cleint. */);
392   GPR_ASSERT(
393       alts_handshaker_client_next(config->client, event, &config->out_frame) ==
394       TSI_INTERNAL_ERROR);
395   alts_tsi_event_destroy(event);
396 
397   /* Cleanup. */
398   destroy_config(config);
399 }
400 
main(int argc,char ** argv)401 int main(int argc, char** argv) {
402   /* Initialization. */
403   grpc_init();
404 
405   /* Tests. */
406   schedule_request_invalid_arg_test();
407   schedule_request_success_test();
408   schedule_request_grpc_call_failure_test();
409 
410   /* Cleanup. */
411   grpc_shutdown();
412   return 0;
413 }
414