Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/aws/s3/private/s3_checksum_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct aws_s3_upload_request_checksum_context {

/* Validation */
size_t encoded_checksum_size;

bool has_review_callback;
};

/**
Expand Down
8 changes: 8 additions & 0 deletions include/aws/s3/private/s3_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,14 @@ int aws_s3_calculate_request_optimal_range_size(
AWS_S3_API
int aws_s3_extract_parts_from_etag(struct aws_byte_cursor etag_header_value, uint32_t *out_num_parts);

/**
* Helper to figure out if given header name is one of the checksum value headers.
* ex. returns true for x-amz-checksum-crc32 or x-amz-checksum-sha256, but false for x-amz-checksum-type.
* Note: relies on hardcoded list of non-checksum headers, which needs to be updated if s3 expands list of those.
*/
AWS_S3_API
bool aws_s3_is_checksum_value_header_name(struct aws_byte_cursor header_name);

AWS_EXTERN_C_END

#endif /* AWS_S3_UTIL_H */
4 changes: 3 additions & 1 deletion source/s3_checksum_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static struct aws_s3_upload_request_checksum_context *s_s3_upload_request_checks
context->algorithm = checksum_config->checksum_algorithm;
context->location = checksum_config->location;
context->encoded_checksum_size = aws_get_digest_size_from_checksum_algorithm(context->algorithm);
context->has_review_callback = checksum_config->full_object_checksum_callback;
Comment thread
DmitriyMusatkin marked this conversation as resolved.
Outdated

/* Convert to base64 encoded size */
size_t encoded_size = 0;
Expand Down Expand Up @@ -115,7 +116,8 @@ struct aws_s3_upload_request_checksum_context *aws_s3_upload_request_checksum_co
}

bool aws_s3_upload_request_checksum_context_should_calculate(struct aws_s3_upload_request_checksum_context *context) {
if (!context || context->algorithm == AWS_SCA_NONE) {
if (!context || context->algorithm == AWS_SCA_NONE || context->algorithm == AWS_SCA_UNKNOWN ||
(context->location == AWS_SCL_NONE && !context->has_review_callback)) {
return false;
}

Expand Down
6 changes: 2 additions & 4 deletions source/s3_checksums.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,6 @@ int aws_checksum_compute(
}
}

static const struct aws_byte_cursor s_checksum_prefix = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-");

static void s_byte_buf_to_upper(struct aws_byte_buf *buf) {
AWS_PRECONDITION(buf);

Expand Down Expand Up @@ -489,7 +487,7 @@ static int s_init_and_verify_checksum_config_from_headers(
return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
}

if (aws_byte_cursor_starts_with_ignore_case(&header.name, &s_checksum_prefix)) {
if (aws_s3_is_checksum_value_header_name(header.name)) {
checksum_header_name = header.name;
has_checksum_value_header = true;
break;
Expand Down Expand Up @@ -551,7 +549,7 @@ static int s_init_and_verify_checksum_config_from_headers(
checksum_config->location = AWS_SCL_NONE;

if (header_algo == AWS_SCA_UNKNOWN) {
aws_byte_cursor_advance(&checksum_header_name, s_checksum_prefix.len);
aws_byte_cursor_advance(&checksum_header_name, sizeof("x-amz-checksum-") - 1);
aws_byte_buf_init_copy_from_cursor(
&checksum_config->unknown_checksum_algo, checksum_config->allocator, checksum_header_name);
s_byte_buf_to_upper(&checksum_config->unknown_checksum_algo);
Expand Down
13 changes: 10 additions & 3 deletions source/s3_default_meta_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ static void s_s3_default_prepare_request_finish(
struct aws_http_message *message = aws_s3_message_util_copy_http_message_no_body_all_headers(
meta_request->allocator, meta_request->initial_request_message);

bool flexible_checksum = meta_request->checksum_config.location != AWS_SCL_NONE;
bool flexible_checksum = meta_request->checksum_config.checksum_algorithm != AWS_SCA_NONE;
if (!flexible_checksum && meta_request->should_compute_content_md5) {
/* If flexible checksum used, client MUST skip Content-MD5 header computation */
aws_s3_message_util_add_content_md5_header(meta_request->allocator, &request->request_body, message);
Expand All @@ -362,8 +362,15 @@ static void s_s3_default_prepare_request_finish(
/* Only PUT Object and Upload part support trailing checksum, that needs the special encoding even if the body
* has 0 length. */
/* Create checksum context from config if needed */
struct aws_s3_upload_request_checksum_context *checksum_context =
aws_s3_upload_request_checksum_context_new(meta_request->allocator, &meta_request->checksum_config);
struct aws_s3_upload_request_checksum_context *checksum_context = NULL;

/**
* Note: CompleteMPU is unique in the sence that checksum on the object level is the full object checksum for all parts and
* not checksum of the body. So avoid any additional checksum handling if default req is completeMPU.
*/
if (meta_request_default->request_type != AWS_S3_REQUEST_TYPE_COMPLETE_MULTIPART_UPLOAD) {
checksum_context = aws_s3_upload_request_checksum_context_new(meta_request->allocator, &meta_request->checksum_config);
}

aws_s3_message_util_assign_body(
meta_request->allocator, &request->request_body, NULL, message, checksum_context);
Expand Down
3 changes: 1 addition & 2 deletions source/s3_request_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ const struct aws_byte_cursor g_s3_create_session_allowed_headers[] = {
const size_t g_s3_create_session_allowed_headers_count = AWS_ARRAY_SIZE(g_s3_create_session_allowed_headers);

static const struct aws_byte_cursor s_x_amz_meta_prefix = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-meta-");
static const struct aws_byte_cursor s_x_amz_checksum_prefix = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-");

static const struct aws_byte_cursor s_checksum_type_header =
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-type");
Expand Down Expand Up @@ -1234,7 +1233,7 @@ void aws_s3_message_util_copy_headers(
}

if (exclude_x_amz_checksum) {
if (aws_byte_cursor_starts_with_ignore_case(&header.name, &s_x_amz_checksum_prefix)) {
if (aws_s3_is_checksum_value_header_name(header.name)) {
continue;
}
}
Expand Down
9 changes: 9 additions & 0 deletions source/s3_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,3 +1019,12 @@ int aws_s3_extract_parts_from_etag(struct aws_byte_cursor etag_header_value, uin

return AWS_OP_SUCCESS;
}

static const struct aws_byte_cursor s_checksum_prefix = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-");

bool aws_s3_is_checksum_value_header_name(struct aws_byte_cursor header_name) {
return aws_byte_cursor_starts_with_ignore_case(&header_name, &s_checksum_prefix) &&
!aws_byte_cursor_eq_c_str_ignore_case(&header_name, "x-amz-checksum-type") &&
!aws_byte_cursor_eq_c_str_ignore_case(&header_name, "x-amz-checksum-mode") &&
!aws_byte_cursor_eq_c_str_ignore_case(&header_name, "x-amz-checksum-algorithm");
}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ add_test_case(test_s3_calculate_client_optimal_range_size)
add_test_case(test_s3_calculate_request_optimal_range_size)
add_test_case(test_s3_extract_parts_from_etag)
add_test_case(test_add_user_agent_header)
add_test_case(test_s3_checksum_header)

add_test_case(test_get_existing_platform_info)
add_test_case(test_get_nonexistent_platform_info)
Expand Down
30 changes: 30 additions & 0 deletions tests/s3_checksum_context_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static int s_test_upload_request_checksum_context_get_checksum_cursor(struct aws

return AWS_OP_SUCCESS;
}

AWS_TEST_CASE(
test_upload_request_checksum_context_get_checksum_cursor,
s_test_upload_request_checksum_context_get_checksum_cursor)
Expand Down Expand Up @@ -80,6 +81,35 @@ static int s_test_upload_request_checksum_context_error_cases(struct aws_allocat
ASSERT_NULL(aws_s3_upload_request_checksum_context_acquire(NULL));
ASSERT_NULL(aws_s3_upload_request_checksum_context_release(NULL));

/* unknown algo */
struct aws_s3_meta_request_checksum_config_storage config2 = {
.allocator = allocator,
.checksum_algorithm = AWS_SCA_UNKNOWN,
.location = AWS_SCL_NONE,
.has_full_object_checksum = false,
};
struct aws_s3_upload_request_checksum_context *context2 =
aws_s3_upload_request_checksum_context_new(allocator, &config2);

ASSERT_NOT_NULL(context2);
ASSERT_FALSE(aws_s3_upload_request_checksum_context_should_calculate(context2));

/* unknown algo */
struct aws_s3_meta_request_checksum_config_storage config3 = {
.allocator = allocator,
.checksum_algorithm = AWS_SCA_CRC32,
.location = AWS_SCL_NONE,
.has_full_object_checksum = false,
};
struct aws_s3_upload_request_checksum_context *context3 =
aws_s3_upload_request_checksum_context_new(allocator, &config3);

ASSERT_NOT_NULL(context3);
ASSERT_FALSE(aws_s3_upload_request_checksum_context_should_calculate(context3));

aws_s3_upload_request_checksum_context_release(context2);
aws_s3_upload_request_checksum_context_release(context3);

return AWS_OP_SUCCESS;
}
AWS_TEST_CASE(test_upload_request_checksum_context_error_cases, s_test_upload_request_checksum_context_error_cases)
Expand Down
17 changes: 17 additions & 0 deletions tests/s3_util_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,3 +1046,20 @@ static int s_test_s3_extract_parts_from_etag(struct aws_allocator *allocator, vo
aws_s3_library_clean_up();
return 0;
}

AWS_TEST_CASE(test_s3_checksum_header, s_test_s3_checksum_header)
static int s_test_s3_checksum_header(struct aws_allocator *allocator, void *ctx) {
(void)ctx;
aws_s3_library_init(allocator);

ASSERT_TRUE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-crc32")));
ASSERT_TRUE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-foo")));
Comment thread
DmitriyMusatkin marked this conversation as resolved.
ASSERT_TRUE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-md5")));

ASSERT_FALSE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-type")));
ASSERT_FALSE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-mode")));
ASSERT_FALSE(aws_s3_is_checksum_value_header_name(aws_byte_cursor_from_c_str("x-amz-checksum-algorithm")));

aws_s3_library_clean_up();
return 0;
}
Loading