diff --git a/.github/workflows/stale_issue.yml b/.github/workflows/stale_issue.yml index 5624eec4b..bdc95a6fd 100644 --- a/.github/workflows/stale_issue.yml +++ b/.github/workflows/stale_issue.yml @@ -9,6 +9,9 @@ jobs: cleanup: runs-on: ubuntu-latest name: Stale issue job + permissions: + issues: write + pull-requests: write steps: - uses: aws-actions/stale-issue-cleanup@v3 with: diff --git a/include/aws/io/io.h b/include/aws/io/io.h index 0ce3f2bc8..fc9677fdb 100644 --- a/include/aws/io/io.h +++ b/include/aws/io/io.h @@ -250,6 +250,8 @@ enum aws_io_errors { AWS_IO_STREAM_SEEK_UNSUPPORTED, AWS_IO_STREAM_GET_LENGTH_UNSUPPORTED, + AWS_IO_TLS_ERROR_READ_FAILURE, + AWS_IO_ERROR_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_IO_PACKAGE_ID), AWS_IO_INVALID_FILE_HANDLE = AWS_ERROR_INVALID_FILE_HANDLE, }; diff --git a/source/darwin/secure_transport_tls_channel_handler.c b/source/darwin/secure_transport_tls_channel_handler.c index 23e49ad25..5846807e4 100644 --- a/source/darwin/secure_transport_tls_channel_handler.c +++ b/source/darwin/secure_transport_tls_channel_handler.c @@ -639,9 +639,8 @@ static int s_process_read_message( (int)status); if (status != errSSLClosedGraceful) { - aws_raise_error(AWS_IO_TLS_ERROR_ALERT_RECEIVED); - aws_channel_shutdown( - secure_transport_handler->parent_slot->channel, AWS_IO_TLS_ERROR_ALERT_RECEIVED); + aws_raise_error(AWS_IO_TLS_ERROR_READ_FAILURE); + aws_channel_shutdown(secure_transport_handler->parent_slot->channel, AWS_IO_TLS_ERROR_READ_FAILURE); } else { AWS_LOGF_TRACE(AWS_LS_IO_TLS, "id=%p: connection shutting down gracefully.", (void *)handler); aws_channel_shutdown(secure_transport_handler->parent_slot->channel, AWS_ERROR_SUCCESS); diff --git a/source/io.c b/source/io.c index b11e38456..79393dd37 100644 --- a/source/io.c +++ b/source/io.c @@ -302,6 +302,10 @@ static struct aws_error_info s_errors[] = { AWS_DEFINE_ERROR_INFO_IO( AWS_IO_STREAM_GET_LENGTH_UNSUPPORTED, "Get length is not supported in the underlying I/O source."), + AWS_DEFINE_ERROR_INFO_IO( + AWS_IO_TLS_ERROR_READ_FAILURE, + "Failure during TLS read."), + }; /* clang-format on */ diff --git a/source/s2n/s2n_tls_channel_handler.c b/source/s2n/s2n_tls_channel_handler.c index bc30ca73b..01052e8c9 100644 --- a/source/s2n/s2n_tls_channel_handler.c +++ b/source/s2n/s2n_tls_channel_handler.c @@ -523,7 +523,7 @@ static int s_s2n_handler_process_read_message( AWS_LOGF_TRACE( AWS_LS_IO_TLS, "id=%p: Downstream window %llu", (void *)handler, (unsigned long long)downstream_window); - while (processed < downstream_window && blocked == S2N_NOT_BLOCKED) { + while (processed < downstream_window) { struct aws_io_message *outgoing_read_message = aws_channel_acquire_message_from_pool( slot->channel, AWS_IO_MESSAGE_APPLICATION_DATA, downstream_window - processed); @@ -558,9 +558,24 @@ static int s_s2n_handler_process_read_message( if (read < 0) { aws_mem_release(outgoing_read_message->allocator, outgoing_read_message); - continue; + + /* the socket blocked so exit from the loop */ + if (s2n_error_get_type(s2n_errno) == S2N_ERR_T_BLOCKED) { + break; + } + + /* the socket returned a fatal error so shut down */ + AWS_LOGF_ERROR( + AWS_LS_IO_TLS, + "id=%p: S2N failed to read with error: %s (%s)", + (void *)handler, + s2n_strerror(s2n_errno, "EN"), + s2n_strerror_debug(s2n_errno, "EN")); + aws_channel_shutdown(slot->channel, AWS_IO_TLS_ERROR_READ_FAILURE); + return AWS_OP_SUCCESS; }; + /* if read > 0 */ processed += read; outgoing_read_message->message_data.len = (size_t)read; diff --git a/source/windows/secure_channel_tls_handler.c b/source/windows/secure_channel_tls_handler.c index 415da7034..9ede8ded5 100644 --- a/source/windows/secure_channel_tls_handler.c +++ b/source/windows/secure_channel_tls_handler.c @@ -1053,7 +1053,7 @@ static int s_do_application_data_decrypt(struct aws_channel_handler *handler) { int error = AWS_OP_ERR; /* when we get an Extra buffer we have to move the pointer and replay the buffer, so we loop until we don't have any extra buffers left over, in the last phase, we then go ahead and send the output. This state function will - always say BLOCKED_ON_READ or SUCCESS. There will never be left over reads.*/ + always say BLOCKED_ON_READ, AWS_IO_TLS_ERROR_READ_FAILURE or SUCCESS. There will never be left over reads.*/ do { error = AWS_OP_ERR; /* 4 buffers are needed, only one is input, the others get zeroed out for the output operation. */ @@ -1079,6 +1079,7 @@ static int s_do_application_data_decrypt(struct aws_channel_handler *handler) { SECURITY_STATUS status = DecryptMessage(&sc_handler->sec_handle, &buffer_desc, 0, NULL); if (status == SEC_E_OK) { + error = AWS_OP_SUCCESS; /* if SECBUFFER_DATA is the buffer type of the second buffer, we have decrypted data to process. If SECBUFFER_DATA is the type for the fourth buffer we need to keep track of it so we can shift everything before doing another decrypt operation. @@ -1144,8 +1145,7 @@ static int s_do_application_data_decrypt(struct aws_channel_handler *handler) { } else { AWS_LOGF_ERROR( AWS_LS_IO_TLS, "id=%p: Error decrypting message. SECURITY_STATUS is %d.", (void *)handler, (int)status); - int aws_error = s_determine_sspi_error(status); - aws_raise_error(aws_error); + aws_raise_error(AWS_IO_TLS_ERROR_READ_FAILURE); } } while (sc_handler->read_extra);