diff options
-rw-r--r-- | src/core/tsi/transport_security.c | 36 | ||||
-rw-r--r-- | src/core/tsi/transport_security_adapter.c | 62 | ||||
-rw-r--r-- | src/core/tsi/transport_security_adapter.h | 11 | ||||
-rw-r--r-- | src/core/tsi/transport_security_interface.h | 89 |
4 files changed, 93 insertions, 105 deletions
diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c index aa8808ab74..b11c00c43c 100644 --- a/src/core/tsi/transport_security.c +++ b/src/core/tsi/transport_security.c @@ -94,6 +94,9 @@ tsi_result tsi_frame_protector_protect(tsi_frame_protector *self, protected_output_frames_size == NULL) { return TSI_INVALID_ARGUMENT; } + if (self->vtable == NULL || self->vtable->protect == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->protect(self, unprotected_bytes, unprotected_bytes_size, protected_output_frames, protected_output_frames_size); @@ -106,6 +109,9 @@ tsi_result tsi_frame_protector_protect_flush( protected_output_frames_size == NULL || still_pending_size == NULL) { return TSI_INVALID_ARGUMENT; } + if (self->vtable == NULL || self->vtable->protect_flush == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->protect_flush(self, protected_output_frames, protected_output_frames_size, still_pending_size); @@ -120,6 +126,9 @@ tsi_result tsi_frame_protector_unprotect( unprotected_bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } + if (self->vtable == NULL || self->vtable->unprotect == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->unprotect(self, protected_frames_bytes, protected_frames_bytes_size, unprotected_bytes, unprotected_bytes_size); @@ -141,6 +150,9 @@ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->vtable == NULL || self->vtable->get_bytes_to_send_to_peer == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size); } @@ -151,12 +163,18 @@ tsi_result tsi_handshaker_process_bytes_from_peer(tsi_handshaker *self, return TSI_INVALID_ARGUMENT; } if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->vtable == NULL || self->vtable->process_bytes_from_peer == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->process_bytes_from_peer(self, bytes, bytes_size); } tsi_result tsi_handshaker_get_result(tsi_handshaker *self) { if (self == NULL) return TSI_INVALID_ARGUMENT; if (self->frame_protector_created) return TSI_FAILED_PRECONDITION; + if (self->vtable == NULL || self->vtable->get_result == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->get_result(self); } @@ -167,6 +185,9 @@ tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer) { if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } + if (self->vtable == NULL || self->vtable->extract_peer == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->extract_peer(self, peer); } @@ -179,6 +200,9 @@ tsi_result tsi_handshaker_create_frame_protector( if (tsi_handshaker_get_result(self) != TSI_OK) { return TSI_FAILED_PRECONDITION; } + if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) { + return TSI_UNIMPLEMENTED; + } result = self->vtable->create_frame_protector(self, max_protected_frame_size, protector); if (result == TSI_OK) { @@ -194,6 +218,9 @@ tsi_result tsi_handshaker_next( tsi_handshaker_on_next_done_cb cb, void *user_data) { if (self == NULL) return TSI_INVALID_ARGUMENT; if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION; + if (self->vtable == NULL || self->vtable->next == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->next(self, received_bytes, received_bytes_size, bytes_to_send, bytes_to_send_size, handshaker_result, cb, user_data); @@ -210,6 +237,9 @@ tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result *self, tsi_peer *peer) { if (self == NULL || peer == NULL) return TSI_INVALID_ARGUMENT; memset(peer, 0, sizeof(tsi_peer)); + if (self->vtable == NULL || self->vtable->extract_peer == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->extract_peer(self, peer); } @@ -217,6 +247,9 @@ tsi_result tsi_handshaker_result_create_frame_protector( const tsi_handshaker_result *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { if (self == NULL || protector == NULL) return TSI_INVALID_ARGUMENT; + if (self->vtable == NULL || self->vtable->create_frame_protector == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->create_frame_protector(self, max_protected_frame_size, protector); } @@ -227,6 +260,9 @@ tsi_result tsi_handshaker_result_get_unused_bytes( if (self == NULL || bytes == NULL || bytes_size == NULL) { return TSI_INVALID_ARGUMENT; } + if (self->vtable == NULL || self->vtable->get_unused_bytes == NULL) { + return TSI_UNIMPLEMENTED; + } return self->vtable->get_unused_bytes(self, bytes, bytes_size); } diff --git a/src/core/tsi/transport_security_adapter.c b/src/core/tsi/transport_security_adapter.c index ebf0279139..d83339b3eb 100644 --- a/src/core/tsi/transport_security_adapter.c +++ b/src/core/tsi/transport_security_adapter.c @@ -45,26 +45,26 @@ typedef struct { tsi_handshaker_result base; - tsi_handshaker *handshaker; + tsi_handshaker *wrapped; unsigned char *unused_bytes; size_t unused_bytes_size; } tsi_adapter_handshaker_result; -static tsi_result tsi_adapter_result_extract_peer( - const tsi_handshaker_result *self, tsi_peer *peer) { +static tsi_result adapter_result_extract_peer(const tsi_handshaker_result *self, + tsi_peer *peer) { tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self; - return tsi_handshaker_extract_peer(impl->handshaker, peer); + return tsi_handshaker_extract_peer(impl->wrapped, peer); } -static tsi_result tsi_adapter_result_create_frame_protector( +static tsi_result adapter_result_create_frame_protector( const tsi_handshaker_result *self, size_t *max_output_protected_frame_size, tsi_frame_protector **protector) { tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self; return tsi_handshaker_create_frame_protector( - impl->handshaker, max_output_protected_frame_size, protector); + impl->wrapped, max_output_protected_frame_size, protector); } -static tsi_result tsi_adapter_result_get_unused_bytes( +static tsi_result adapter_result_get_unused_bytes( const tsi_handshaker_result *self, unsigned char **bytes, size_t *byte_size) { tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self; @@ -73,26 +73,26 @@ static tsi_result tsi_adapter_result_get_unused_bytes( return TSI_OK; } -static void tsi_adapter_result_destroy(tsi_handshaker_result *self) { +static void adapter_result_destroy(tsi_handshaker_result *self) { tsi_adapter_handshaker_result *impl = (tsi_adapter_handshaker_result *)self; gpr_free(impl->unused_bytes); gpr_free(self); } static const tsi_handshaker_result_vtable result_vtable = { - tsi_adapter_result_extract_peer, tsi_adapter_result_create_frame_protector, - tsi_adapter_result_get_unused_bytes, tsi_adapter_result_destroy, + adapter_result_extract_peer, adapter_result_create_frame_protector, + adapter_result_get_unused_bytes, adapter_result_destroy, }; tsi_result tsi_adapter_create_handshaker_result( - tsi_handshaker *handshaker, const unsigned char *unused_bytes, + tsi_handshaker *wrapped, const unsigned char *unused_bytes, size_t unused_bytes_size, tsi_handshaker_result **handshaker_result) { - if (handshaker == NULL || (unused_bytes_size > 0 && unused_bytes == NULL)) { + if (wrapped == NULL || (unused_bytes_size > 0 && unused_bytes == NULL)) { return TSI_INVALID_ARGUMENT; } tsi_adapter_handshaker_result *impl = gpr_zalloc(sizeof(*impl)); impl->base.vtable = &result_vtable; - impl->handshaker = handshaker; + impl->wrapped = wrapped; impl->unused_bytes_size = unused_bytes_size; if (unused_bytes_size > 0) { impl->unused_bytes = gpr_malloc(unused_bytes_size); @@ -113,30 +113,30 @@ typedef struct { size_t adapter_buffer_size; } tsi_adapter_handshaker; -static tsi_result tsi_adapter_get_bytes_to_send_to_peer(tsi_handshaker *self, - unsigned char *bytes, - size_t *bytes_size) { +static tsi_result adapter_get_bytes_to_send_to_peer(tsi_handshaker *self, + unsigned char *bytes, + size_t *bytes_size) { return tsi_handshaker_get_bytes_to_send_to_peer( tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size); } -static tsi_result tsi_adapter_process_bytes_from_peer( - tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) { +static tsi_result adapter_process_bytes_from_peer(tsi_handshaker *self, + const unsigned char *bytes, + size_t *bytes_size) { return tsi_handshaker_process_bytes_from_peer( tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size); } -static tsi_result tsi_adapter_get_result(tsi_handshaker *self) { +static tsi_result adapter_get_result(tsi_handshaker *self) { return tsi_handshaker_get_result(tsi_adapter_handshaker_get_wrapped(self)); } -static tsi_result tsi_adapter_extract_peer(tsi_handshaker *self, - tsi_peer *peer) { +static tsi_result adapter_extract_peer(tsi_handshaker *self, tsi_peer *peer) { return tsi_handshaker_extract_peer(tsi_adapter_handshaker_get_wrapped(self), peer); } -static tsi_result tsi_adapter_create_frame_protector( +static tsi_result adapter_create_frame_protector( tsi_handshaker *self, size_t *max_protected_frame_size, tsi_frame_protector **protector) { return tsi_handshaker_create_frame_protector( @@ -144,14 +144,14 @@ static tsi_result tsi_adapter_create_frame_protector( protector); } -static void tsi_adapter_destroy(tsi_handshaker *self) { +static void adapter_destroy(tsi_handshaker *self) { tsi_adapter_handshaker *impl = (tsi_adapter_handshaker *)self; tsi_handshaker_destroy(impl->wrapped); gpr_free(impl->adapter_buffer); gpr_free(self); } -static tsi_result tsi_adapter_next( +static tsi_result adapter_next( tsi_handshaker *self, const unsigned char *received_bytes, size_t received_bytes_size, unsigned char **bytes_to_send, size_t *bytes_to_send_size, tsi_handshaker_result **handshaker_result, @@ -207,13 +207,13 @@ static tsi_result tsi_adapter_next( } static const tsi_handshaker_vtable handshaker_vtable = { - tsi_adapter_get_bytes_to_send_to_peer, - tsi_adapter_process_bytes_from_peer, - tsi_adapter_get_result, - tsi_adapter_extract_peer, - tsi_adapter_create_frame_protector, - tsi_adapter_destroy, - tsi_adapter_next, + adapter_get_bytes_to_send_to_peer, + adapter_process_bytes_from_peer, + adapter_get_result, + adapter_extract_peer, + adapter_create_frame_protector, + adapter_destroy, + adapter_next, }; tsi_handshaker *tsi_create_adapter_handshaker(tsi_handshaker *wrapped) { diff --git a/src/core/tsi/transport_security_adapter.h b/src/core/tsi/transport_security_adapter.h index de5aaefd5f..686618b53b 100644 --- a/src/core/tsi/transport_security_adapter.h +++ b/src/core/tsi/transport_security_adapter.h @@ -41,11 +41,18 @@ extern "C" { #endif /* Create a tsi handshaker that takes an implementation of old interface and - converts into an implementation of new interface. + converts into an implementation of new interface. In the old interface, + there are get_bytes_to_send_to_peer, process_bytes_from_peer, get_result, + extract_peer, and create_frame_protector. In the new interface, only next + method is needed. See transport_security_interface.h for details. Note that + this tsi adapter handshaker is temporary. It will be removed once TSI has + been fully migrated to the new interface. Ownership of input tsi_handshaker is transferred to this new adapter. */ tsi_handshaker *tsi_create_adapter_handshaker(tsi_handshaker *wrapped); -/* Given a tsi adapter handshaker, return the original wrapped handshaker. */ +/* Given a tsi adapter handshaker, return the original wrapped handshaker. The + adapter still owns the wrapped handshaker which should not be destroyed by + the caller. */ tsi_handshaker *tsi_adapter_handshaker_get_wrapped(tsi_handshaker *adapter); #ifdef __cplusplus diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h index c9495f80b6..f2112b62b6 100644 --- a/src/core/tsi/transport_security_interface.h +++ b/src/core/tsi/transport_security_interface.h @@ -232,7 +232,8 @@ tsi_result tsi_handshaker_result_create_frame_protector( /* This method returns the unused bytes from the handshake. It returns TSI_OK assuming there is no fatal error. - The caller should not free the bytes. */ + Ownership of the bytes is retained by the handshaker result. As a + consequence, the caller must not free the bytes. */ tsi_result tsi_handshaker_result_get_unused_bytes( const tsi_handshaker_result *self, unsigned char **bytes, size_t *byte_size); @@ -247,64 +248,6 @@ void tsi_handshaker_result_destroy(tsi_handshaker_result *self); ------------------------------------------------------------------------ - A typical usage of the synchronous TSI handshaker would be: - - ------------------------------------------------------------------------ - tsi_result status = TSI_OK; - unsigned char buf[4096]; - const size_t buf_size = 4906; - size_t bytes_received_size = 0; - unsigned char *bytes_to_send = NULL; - size_t bytes_to_send_size = 0; - tsi_handshaker_result *result = NULL; - - while (1) { - status = tsi_handshaker_next( - handshaker, buf, bytes_received_size, - &bytes_to_send, &bytes_to_send_size, &result, NULL, NULL); - if (status == TSI_INCOMPLETE_DATA) { - // Need more data from the peer. - bytes_received_size = buf_size; - read_bytes_from_peer(buf, &bytes_received_size); - continue; - } - if (status != TSI_OK) return status; - if (bytes_to_send_size > 0) { - send_bytes_to_peer(bytes_to_send, bytes_to_send_size); - } - if (result != NULL) break; - bytes_received_size = buf_size; - read_bytes_from_peer(buf, &bytes_received_size); - } - - // Check the Peer. - tsi_peer peer; - status = tsi_handshaker_result_extract_peer(result, &peer); - if (status != TSI_OK) return status; - status = check_peer(&peer); - tsi_peer_destruct(&peer); - if (status != TSI_OK) return status; - - // Create the protector. - tsi_frame_protector* protector = NULL; - status = tsi_handshaker_result_create_frame_protector(result, NULL, - &protector); - if (status != TSI_OK) return status; - - // Do not forget to unprotect outstanding data if any. - unsigned char *unused_bytes = NULL; - size_t unused_bytes_size = 0; - status = tsi_handshaker_result_get_unused_bytes(result, &unused_bytes, - &unused_bytes_size); - if (status != TSI_OK) return status; - if (unused_bytes_size > 0) { - status = tsi_frame_protector_unprotect(protector, unused_bytes, - unused_bytes_size, ..., ...); - .... - } - ... - ------------------------------------------------------------------------ - A typical usage supporting both synchronous and asynchronous TSI handshaker implementations would be: @@ -324,8 +267,8 @@ void tsi_handshaker_result_destroy(tsi_handshaker_result *self); ... } - // This method is the callback function when there are data received from - // the peer. This method will read bytes into the handshake buffer and call + // This method is the callback function when data is received from the + // peer. This method will read bytes into the handshake buffer and call // do_handshake_next. void on_handshake_data_received_from_peer(void *user_data) { security_handshaker *h = (security_handshaker *)user_data; @@ -396,7 +339,7 @@ void tsi_handshaker_result_destroy(tsi_handshaker_result *self); ------------------------------------------------------------------------ */ typedef struct tsi_handshaker tsi_handshaker; -/* TO BE DEPRECATED SOON. +/* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead. Gets bytes that need to be sent to the peer. - bytes is the buffer that will be written with the data to be sent to the peer. @@ -412,7 +355,7 @@ tsi_result tsi_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self, unsigned char *bytes, size_t *bytes_size); -/* TO BE DEPRECATED SOON. +/* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead. Processes bytes received from the peer. - bytes is the buffer containing the data. - bytes_size is an input/output parameter specifying the size of the data as @@ -439,14 +382,15 @@ tsi_result tsi_handshaker_get_result(tsi_handshaker *self); #define tsi_handshaker_is_in_progress(h) \ (tsi_handshaker_get_result((h)) == TSI_HANDSHAKE_IN_PROGRESS) -/* TO BE DEPRECATED SOON. +/* TO BE DEPRECATED SOON. Use tsi_handshaker_result_extract_peer instead. This method may return TSI_FAILED_PRECONDITION if tsi_handshaker_is_in_progress returns 1, it returns TSI_OK otherwise assuming the handshaker is not in a fatal error state. The caller is responsible for destructing the peer. */ tsi_result tsi_handshaker_extract_peer(tsi_handshaker *self, tsi_peer *peer); -/* TO BE DEPRECATED SOON. +/* TO BE DEPRECATED SOON. Use tsi_handshaker_result_create_frame_protector + instead. This method creates a tsi_frame_protector object after the handshake phase is done. After this method has been called successfully, the only method that can be called on this object is Destroy. @@ -488,13 +432,14 @@ typedef void (*tsi_handshaker_on_next_done_cb)( TSI handshaker implementation. - user_data is the argument to callback function passed from the caller. This method returns TSI_ASYNC if the TSI handshaker implementation is - asynchronous. It returns TSI_OK if the handshake completes or if there are - data to send to the peer, otherwise returns TSI_INCOMPLETE_DATA which - indicates that this method needs to be called again with more data from the - peer. In case of a fatal error in the handshake, another specific error code - is returned. - The caller is responsible for destroying the handshaker_result. However, the - caller should not free bytes_to_send, as the buffer is owned by the + asynchronous, and in this case, the callback is guaranteed to run in another + thread owned by TSI. It returns TSI_OK if the handshake completes or if + there are data to send to the peer, otherwise returns TSI_INCOMPLETE_DATA + which indicates that this method needs to be called again with more data + from the peer. In case of a fatal error in the handshake, another specific + error code is returned. + The caller is responsible for destroying the handshaker_result. However, + the caller should not free bytes_to_send, as the buffer is owned by the tsi_handshaker object. */ tsi_result tsi_handshaker_next( tsi_handshaker *self, const unsigned char *received_bytes, |