diff options
Diffstat (limited to 'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc')
-rw-r--r-- | src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc b/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc new file mode 100644 index 0000000000..256e414ae4 --- /dev/null +++ b/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc @@ -0,0 +1,520 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <grpc/support/port_platform.h> + +#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "src/core/tsi/alts/handshaker/transport_security_common_api.h" + +/* HandshakerReq */ +grpc_gcp_handshaker_req* grpc_gcp_handshaker_req_create( + grpc_gcp_handshaker_req_type type) { + grpc_gcp_handshaker_req* req = + static_cast<grpc_gcp_handshaker_req*>(gpr_zalloc(sizeof(*req))); + switch (type) { + case CLIENT_START_REQ: + req->has_client_start = true; + break; + case SERVER_START_REQ: + req->has_server_start = true; + break; + case NEXT_REQ: + req->has_next = true; + break; + } + return req; +} + +void grpc_gcp_handshaker_req_destroy(grpc_gcp_handshaker_req* req) { + if (req == nullptr) { + return; + } + if (req->has_client_start) { + /* Destroy client_start request. */ + destroy_repeated_field_list_identity( + static_cast<repeated_field*>(req->client_start.target_identities.arg)); + destroy_repeated_field_list_string(static_cast<repeated_field*>( + req->client_start.application_protocols.arg)); + destroy_repeated_field_list_string( + static_cast<repeated_field*>(req->client_start.record_protocols.arg)); + if (req->client_start.has_local_identity) { + destroy_slice(static_cast<grpc_slice*>( + req->client_start.local_identity.hostname.arg)); + destroy_slice(static_cast<grpc_slice*>( + req->client_start.local_identity.service_account.arg)); + } + if (req->client_start.has_local_endpoint) { + destroy_slice(static_cast<grpc_slice*>( + req->client_start.local_endpoint.ip_address.arg)); + } + if (req->client_start.has_remote_endpoint) { + destroy_slice(static_cast<grpc_slice*>( + req->client_start.remote_endpoint.ip_address.arg)); + } + destroy_slice(static_cast<grpc_slice*>(req->client_start.target_name.arg)); + } else if (req->has_server_start) { + /* Destroy server_start request. */ + size_t i = 0; + for (i = 0; i < req->server_start.handshake_parameters_count; i++) { + destroy_repeated_field_list_identity( + static_cast<repeated_field*>(req->server_start.handshake_parameters[i] + .value.local_identities.arg)); + destroy_repeated_field_list_string( + static_cast<repeated_field*>(req->server_start.handshake_parameters[i] + .value.record_protocols.arg)); + } + destroy_repeated_field_list_string(static_cast<repeated_field*>( + req->server_start.application_protocols.arg)); + if (req->server_start.has_local_endpoint) { + destroy_slice(static_cast<grpc_slice*>( + req->server_start.local_endpoint.ip_address.arg)); + } + if (req->server_start.has_remote_endpoint) { + destroy_slice(static_cast<grpc_slice*>( + req->server_start.remote_endpoint.ip_address.arg)); + } + destroy_slice(static_cast<grpc_slice*>(req->server_start.in_bytes.arg)); + } else { + /* Destroy next request. */ + destroy_slice(static_cast<grpc_slice*>(req->next.in_bytes.arg)); + } + gpr_free(req); +} + +bool grpc_gcp_handshaker_req_set_handshake_protocol( + grpc_gcp_handshaker_req* req, + grpc_gcp_handshake_protocol handshake_protocol) { + if (req == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_handshake_protocol()."); + return false; + } + req->client_start.has_handshake_security_protocol = true; + req->client_start.handshake_security_protocol = handshake_protocol; + return true; +} + +bool grpc_gcp_handshaker_req_set_target_name(grpc_gcp_handshaker_req* req, + const char* target_name) { + if (req == nullptr || target_name == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_target_name()."); + return false; + } + grpc_slice* slice = create_slice(target_name, strlen(target_name)); + req->client_start.target_name.arg = slice; + req->client_start.target_name.funcs.encode = encode_string_or_bytes_cb; + return true; +} + +bool grpc_gcp_handshaker_req_add_application_protocol( + grpc_gcp_handshaker_req* req, const char* application_protocol) { + if (req == nullptr || application_protocol == nullptr || req->has_next) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_add_application_protocol()."); + return false; + } + grpc_slice* slice = + create_slice(application_protocol, strlen(application_protocol)); + if (req->has_client_start) { + add_repeated_field(reinterpret_cast<repeated_field**>( + &req->client_start.application_protocols.arg), + slice); + req->client_start.application_protocols.funcs.encode = + encode_repeated_string_cb; + } else { + add_repeated_field(reinterpret_cast<repeated_field**>( + &req->server_start.application_protocols.arg), + slice); + req->server_start.application_protocols.funcs.encode = + encode_repeated_string_cb; + } + return true; +} + +bool grpc_gcp_handshaker_req_add_record_protocol(grpc_gcp_handshaker_req* req, + const char* record_protocol) { + if (req == nullptr || record_protocol == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_add_record_protocol()."); + return false; + } + grpc_slice* slice = create_slice(record_protocol, strlen(record_protocol)); + add_repeated_field(reinterpret_cast<repeated_field**>( + &req->client_start.record_protocols.arg), + slice); + req->client_start.record_protocols.funcs.encode = encode_repeated_string_cb; + return true; +} + +static void set_identity_hostname(grpc_gcp_identity* identity, + const char* hostname) { + grpc_slice* slice = create_slice(hostname, strlen(hostname)); + identity->hostname.arg = slice; + identity->hostname.funcs.encode = encode_string_or_bytes_cb; +} + +static void set_identity_service_account(grpc_gcp_identity* identity, + const char* service_account) { + grpc_slice* slice = create_slice(service_account, strlen(service_account)); + identity->service_account.arg = slice; + identity->service_account.funcs.encode = encode_string_or_bytes_cb; +} + +bool grpc_gcp_handshaker_req_add_target_identity_hostname( + grpc_gcp_handshaker_req* req, const char* hostname) { + if (req == nullptr || hostname == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_gcp_handshaker_req_add_target_identity_hostname()."); + return false; + } + grpc_gcp_identity* target_identity = + static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*target_identity))); + set_identity_hostname(target_identity, hostname); + req->client_start.target_identities.funcs.encode = + encode_repeated_identity_cb; + add_repeated_field(reinterpret_cast<repeated_field**>( + &req->client_start.target_identities.arg), + target_identity); + return true; +} + +bool grpc_gcp_handshaker_req_add_target_identity_service_account( + grpc_gcp_handshaker_req* req, const char* service_account) { + if (req == nullptr || service_account == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_gcp_handshaker_req_add_target_identity_service_account()."); + return false; + } + grpc_gcp_identity* target_identity = + static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*target_identity))); + set_identity_service_account(target_identity, service_account); + req->client_start.target_identities.funcs.encode = + encode_repeated_identity_cb; + add_repeated_field(reinterpret_cast<repeated_field**>( + &req->client_start.target_identities.arg), + target_identity); + return true; +} + +bool grpc_gcp_handshaker_req_set_local_identity_hostname( + grpc_gcp_handshaker_req* req, const char* hostname) { + if (req == nullptr || hostname == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_gcp_handshaker_req_set_local_identity_hostname()."); + return false; + } + req->client_start.has_local_identity = true; + set_identity_hostname(&req->client_start.local_identity, hostname); + return true; +} + +bool grpc_gcp_handshaker_req_set_local_identity_service_account( + grpc_gcp_handshaker_req* req, const char* service_account) { + if (req == nullptr || service_account == nullptr || !req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to " + "grpc_gcp_handshaker_req_set_local_identity_service_account()."); + return false; + } + req->client_start.has_local_identity = true; + set_identity_service_account(&req->client_start.local_identity, + service_account); + return true; +} + +static void set_endpoint(grpc_gcp_endpoint* endpoint, const char* ip_address, + size_t port, grpc_gcp_network_protocol protocol) { + grpc_slice* slice = create_slice(ip_address, strlen(ip_address)); + endpoint->ip_address.arg = slice; + endpoint->ip_address.funcs.encode = encode_string_or_bytes_cb; + endpoint->has_port = true; + endpoint->port = static_cast<int32_t>(port); + endpoint->has_protocol = true; + endpoint->protocol = protocol; +} + +bool grpc_gcp_handshaker_req_set_rpc_versions(grpc_gcp_handshaker_req* req, + uint32_t max_major, + uint32_t max_minor, + uint32_t min_major, + uint32_t min_minor) { + if (req == nullptr || req->has_next) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_rpc_versions()."); + return false; + } + if (req->has_client_start) { + req->client_start.has_rpc_versions = true; + grpc_gcp_rpc_protocol_versions_set_max(&req->client_start.rpc_versions, + max_major, max_minor); + grpc_gcp_rpc_protocol_versions_set_min(&req->client_start.rpc_versions, + min_major, min_minor); + } else { + req->server_start.has_rpc_versions = true; + grpc_gcp_rpc_protocol_versions_set_max(&req->server_start.rpc_versions, + max_major, max_minor); + grpc_gcp_rpc_protocol_versions_set_min(&req->server_start.rpc_versions, + min_major, min_minor); + } + return true; +} + +bool grpc_gcp_handshaker_req_set_local_endpoint( + grpc_gcp_handshaker_req* req, const char* ip_address, size_t port, + grpc_gcp_network_protocol protocol) { + if (req == nullptr || ip_address == nullptr || port > 65535 || + req->has_next) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_local_endpoint()."); + return false; + } + if (req->has_client_start) { + req->client_start.has_local_endpoint = true; + set_endpoint(&req->client_start.local_endpoint, ip_address, port, protocol); + } else { + req->server_start.has_local_endpoint = true; + set_endpoint(&req->server_start.local_endpoint, ip_address, port, protocol); + } + return true; +} + +bool grpc_gcp_handshaker_req_set_remote_endpoint( + grpc_gcp_handshaker_req* req, const char* ip_address, size_t port, + grpc_gcp_network_protocol protocol) { + if (req == nullptr || ip_address == nullptr || port > 65535 || + req->has_next) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_remote_endpoint()."); + return false; + } + if (req->has_client_start) { + req->client_start.has_remote_endpoint = true; + set_endpoint(&req->client_start.remote_endpoint, ip_address, port, + protocol); + } else { + req->server_start.has_remote_endpoint = true; + set_endpoint(&req->server_start.remote_endpoint, ip_address, port, + protocol); + } + return true; +} + +bool grpc_gcp_handshaker_req_set_in_bytes(grpc_gcp_handshaker_req* req, + const char* in_bytes, size_t size) { + if (req == nullptr || in_bytes == nullptr || req->has_client_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_set_in_bytes()."); + return false; + } + grpc_slice* slice = create_slice(in_bytes, size); + if (req->has_next) { + req->next.in_bytes.arg = slice; + req->next.in_bytes.funcs.encode = &encode_string_or_bytes_cb; + } else { + req->server_start.in_bytes.arg = slice; + req->server_start.in_bytes.funcs.encode = &encode_string_or_bytes_cb; + } + return true; +} + +static grpc_gcp_server_handshake_parameters* server_start_find_param( + grpc_gcp_handshaker_req* req, int32_t key) { + size_t i = 0; + for (i = 0; i < req->server_start.handshake_parameters_count; i++) { + if (req->server_start.handshake_parameters[i].key == key) { + return &req->server_start.handshake_parameters[i].value; + } + } + req->server_start + .handshake_parameters[req->server_start.handshake_parameters_count] + .has_key = true; + req->server_start + .handshake_parameters[req->server_start.handshake_parameters_count] + .has_value = true; + req->server_start + .handshake_parameters[req->server_start.handshake_parameters_count++] + .key = key; + return &req->server_start + .handshake_parameters + [req->server_start.handshake_parameters_count - 1] + .value; +} + +bool grpc_gcp_handshaker_req_param_add_record_protocol( + grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key, + const char* record_protocol) { + if (req == nullptr || record_protocol == nullptr || !req->has_server_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_param_add_record_protocol()."); + return false; + } + grpc_gcp_server_handshake_parameters* param = + server_start_find_param(req, key); + grpc_slice* slice = create_slice(record_protocol, strlen(record_protocol)); + add_repeated_field( + reinterpret_cast<repeated_field**>(¶m->record_protocols.arg), slice); + param->record_protocols.funcs.encode = &encode_repeated_string_cb; + return true; +} + +bool grpc_gcp_handshaker_req_param_add_local_identity_hostname( + grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key, + const char* hostname) { + if (req == nullptr || hostname == nullptr || !req->has_server_start) { + gpr_log(GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_param_add_local_identity_hostname()."); + return false; + } + grpc_gcp_server_handshake_parameters* param = + server_start_find_param(req, key); + grpc_gcp_identity* local_identity = + static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*local_identity))); + set_identity_hostname(local_identity, hostname); + add_repeated_field( + reinterpret_cast<repeated_field**>(¶m->local_identities.arg), + local_identity); + param->local_identities.funcs.encode = &encode_repeated_identity_cb; + return true; +} + +bool grpc_gcp_handshaker_req_param_add_local_identity_service_account( + grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key, + const char* service_account) { + if (req == nullptr || service_account == nullptr || !req->has_server_start) { + gpr_log( + GPR_ERROR, + "Invalid arguments to " + "grpc_gcp_handshaker_req_param_add_local_identity_service_account()."); + return false; + } + grpc_gcp_server_handshake_parameters* param = + server_start_find_param(req, key); + grpc_gcp_identity* local_identity = + static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*local_identity))); + set_identity_service_account(local_identity, service_account); + add_repeated_field( + reinterpret_cast<repeated_field**>(¶m->local_identities.arg), + local_identity); + param->local_identities.funcs.encode = &encode_repeated_identity_cb; + return true; +} + +bool grpc_gcp_handshaker_req_encode(grpc_gcp_handshaker_req* req, + grpc_slice* slice) { + if (req == nullptr || slice == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr arguments to grpc_gcp_handshaker_req_encode()."); + return false; + } + pb_ostream_t size_stream; + memset(&size_stream, 0, sizeof(pb_ostream_t)); + if (!pb_encode(&size_stream, grpc_gcp_HandshakerReq_fields, req)) { + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream)); + return false; + } + size_t encoded_length = size_stream.bytes_written; + *slice = grpc_slice_malloc(encoded_length); + pb_ostream_t output_stream = + pb_ostream_from_buffer(GRPC_SLICE_START_PTR(*slice), encoded_length); + if (!pb_encode(&output_stream, grpc_gcp_HandshakerReq_fields, req) != 0) { + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&output_stream)); + return false; + } + return true; +} + +/* HandshakerResp. */ +grpc_gcp_handshaker_resp* grpc_gcp_handshaker_resp_create(void) { + grpc_gcp_handshaker_resp* resp = + static_cast<grpc_gcp_handshaker_resp*>(gpr_zalloc(sizeof(*resp))); + return resp; +} + +void grpc_gcp_handshaker_resp_destroy(grpc_gcp_handshaker_resp* resp) { + if (resp != nullptr) { + destroy_slice(static_cast<grpc_slice*>(resp->out_frames.arg)); + if (resp->has_status) { + destroy_slice(static_cast<grpc_slice*>(resp->status.details.arg)); + } + if (resp->has_result) { + destroy_slice( + static_cast<grpc_slice*>(resp->result.application_protocol.arg)); + destroy_slice(static_cast<grpc_slice*>(resp->result.record_protocol.arg)); + destroy_slice(static_cast<grpc_slice*>(resp->result.key_data.arg)); + if (resp->result.has_local_identity) { + destroy_slice( + static_cast<grpc_slice*>(resp->result.local_identity.hostname.arg)); + destroy_slice(static_cast<grpc_slice*>( + resp->result.local_identity.service_account.arg)); + } + if (resp->result.has_peer_identity) { + destroy_slice( + static_cast<grpc_slice*>(resp->result.peer_identity.hostname.arg)); + destroy_slice(static_cast<grpc_slice*>( + resp->result.peer_identity.service_account.arg)); + } + } + gpr_free(resp); + } +} + +bool grpc_gcp_handshaker_resp_decode(grpc_slice encoded_handshaker_resp, + grpc_gcp_handshaker_resp* resp) { + if (resp == nullptr) { + gpr_log(GPR_ERROR, + "Invalid nullptr argument to grpc_gcp_handshaker_resp_decode()."); + return false; + } + pb_istream_t stream = + pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_handshaker_resp), + GRPC_SLICE_LENGTH(encoded_handshaker_resp)); + resp->out_frames.funcs.decode = decode_string_or_bytes_cb; + resp->status.details.funcs.decode = decode_string_or_bytes_cb; + resp->result.application_protocol.funcs.decode = decode_string_or_bytes_cb; + resp->result.record_protocol.funcs.decode = decode_string_or_bytes_cb; + resp->result.key_data.funcs.decode = decode_string_or_bytes_cb; + resp->result.peer_identity.hostname.funcs.decode = decode_string_or_bytes_cb; + resp->result.peer_identity.service_account.funcs.decode = + decode_string_or_bytes_cb; + resp->result.local_identity.hostname.funcs.decode = decode_string_or_bytes_cb; + resp->result.local_identity.service_account.funcs.decode = + decode_string_or_bytes_cb; + if (!pb_decode(&stream, grpc_gcp_HandshakerResp_fields, resp)) { + gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); + return false; + } + return true; +} |