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