diff --git a/aws-common-runtime/aws-c-auth b/aws-common-runtime/aws-c-auth index 040c77bcc..7c978ed33 160000 --- a/aws-common-runtime/aws-c-auth +++ b/aws-common-runtime/aws-c-auth @@ -1 +1 @@ -Subproject commit 040c77bcc184d943734086e99e777968ab96cffb +Subproject commit 7c978ed334c51d9af19616042acdcf37a0a1dad4 diff --git a/aws-common-runtime/aws-c-cal b/aws-common-runtime/aws-c-cal index 3215b8f64..1c087719f 160000 --- a/aws-common-runtime/aws-c-cal +++ b/aws-common-runtime/aws-c-cal @@ -1 +1 @@ -Subproject commit 3215b8f640056487205bea4306ee5e6794748c01 +Subproject commit 1c087719f78442f2ceb7bc8c79ac1e5f27bfc2d0 diff --git a/aws-common-runtime/aws-c-common b/aws-common-runtime/aws-c-common index fa67d3bb7..f6f914598 160000 --- a/aws-common-runtime/aws-c-common +++ b/aws-common-runtime/aws-c-common @@ -1 +1 @@ -Subproject commit fa67d3bb7fb77899088df84c9d1b9a2f7c084efc +Subproject commit f6f9145982f60ce2c92f9f0f2796b1b150e6f991 diff --git a/aws-common-runtime/aws-c-http b/aws-common-runtime/aws-c-http index 359dfe5e5..e8e08d05f 160000 --- a/aws-common-runtime/aws-c-http +++ b/aws-common-runtime/aws-c-http @@ -1 +1 @@ -Subproject commit 359dfe5e56889f9387d79ff14e9faee5313fbfb9 +Subproject commit e8e08d05fea8ad73fb61ebdb9345a55dfebe33cf diff --git a/aws-common-runtime/aws-c-io b/aws-common-runtime/aws-c-io index 172793631..d4f4106de 160000 --- a/aws-common-runtime/aws-c-io +++ b/aws-common-runtime/aws-c-io @@ -1 +1 @@ -Subproject commit 1727936314cfaf8a769663870b6bafd72aea6f12 +Subproject commit d4f4106def191e0424851fe7b8e69058bccb0bbc diff --git a/aws-common-runtime/aws-c-mqtt b/aws-common-runtime/aws-c-mqtt index 45e054d19..631104fea 160000 --- a/aws-common-runtime/aws-c-mqtt +++ b/aws-common-runtime/aws-c-mqtt @@ -1 +1 @@ -Subproject commit 45e054d191ef3d40305d934ff95c32adf44edc7c +Subproject commit 631104feadca6bba1ab9dc534ec5dfe1435678d0 diff --git a/src/main/java/software/amazon/awssdk/crt/auth/signing/AwsSigningConfig.java b/src/main/java/software/amazon/awssdk/crt/auth/signing/AwsSigningConfig.java index 2778d0055..341da54aa 100644 --- a/src/main/java/software/amazon/awssdk/crt/auth/signing/AwsSigningConfig.java +++ b/src/main/java/software/amazon/awssdk/crt/auth/signing/AwsSigningConfig.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.Map; +import software.amazon.awssdk.crt.auth.credentials.Credentials; import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; import software.amazon.awssdk.crt.CrtResource; @@ -27,8 +28,7 @@ public class AwsSigningConfig extends CrtResource { public enum AwsSigningAlgorithm { - SIGV4_HEADER(0), - SIGV4_QUERY_PARAM(1); + SIGV4(0); AwsSigningAlgorithm(int nativeValue) { this.nativeValue = nativeValue; @@ -47,8 +47,7 @@ public static AwsSigningAlgorithm getEnumValueFromInteger(int value) { private static Map buildEnumMapping() { Map enumMapping = new HashMap(); - enumMapping.put(SIGV4_HEADER.getNativeValue(), SIGV4_HEADER); - enumMapping.put(SIGV4_QUERY_PARAM.getNativeValue(), SIGV4_QUERY_PARAM); + enumMapping.put(SIGV4.getNativeValue(), SIGV4); return enumMapping; } @@ -58,64 +57,146 @@ private static Map buildEnumMapping() { private static Map enumMapping = buildEnumMapping(); } - public enum AwsBodySigningConfigType { - AWS_BODY_SIGNING_OFF(0), - AWS_BODY_SIGNING_ON(1), - AWS_BODY_SIGNING_UNSIGNED_PAYLOAD(2); + public enum AwsSignatureType { + HTTP_REQUEST_VIA_HEADERS(0), + HTTP_REQUEST_VIA_QUERY_PARAMS(1), + HTTP_REQUEST_CHUNK(2), + HTTP_REQUEST_EVENT(3); - AwsBodySigningConfigType(int nativeValue) { + AwsSignatureType(int nativeValue) { this.nativeValue = nativeValue; } public int getNativeValue() { return nativeValue; } - public static AwsBodySigningConfigType getEnumValueFromInteger(int value) { - AwsBodySigningConfigType enumValue = enumMapping.get(value); + public static AwsSignatureType getEnumValueFromInteger(int value) { + AwsSignatureType enumValue = enumMapping.get(value); if (enumValue != null) { return enumValue; } - throw new RuntimeException("Illegal body signing config type value in signing configuration"); + throw new RuntimeException("Illegal signature type value in signing configuration"); } - private static Map buildEnumMapping() { - Map enumMapping = new HashMap(); - enumMapping.put(AWS_BODY_SIGNING_OFF.getNativeValue(), AWS_BODY_SIGNING_OFF); - enumMapping.put(AWS_BODY_SIGNING_ON.getNativeValue(), AWS_BODY_SIGNING_ON); - enumMapping.put(AWS_BODY_SIGNING_UNSIGNED_PAYLOAD.getNativeValue(), AWS_BODY_SIGNING_UNSIGNED_PAYLOAD); + private static Map buildEnumMapping() { + Map enumMapping = new HashMap(); + enumMapping.put(HTTP_REQUEST_VIA_HEADERS.getNativeValue(), HTTP_REQUEST_VIA_HEADERS); + enumMapping.put(HTTP_REQUEST_VIA_QUERY_PARAMS.getNativeValue(), HTTP_REQUEST_VIA_QUERY_PARAMS); + enumMapping.put(HTTP_REQUEST_CHUNK.getNativeValue(), HTTP_REQUEST_CHUNK); + enumMapping.put(HTTP_REQUEST_EVENT.getNativeValue(), HTTP_REQUEST_EVENT); return enumMapping; } private int nativeValue; - private static Map enumMapping = buildEnumMapping(); + private static Map enumMapping = buildEnumMapping(); } - private int signingAlgorithm = AwsSigningAlgorithm.SIGV4_HEADER.getNativeValue(); + public enum AwsSignedBodyValueType { + EMPTY(0), + PAYLOAD(1), + UNSIGNED_PAYLOAD(2), + STREAMING_AWS4_HMAC_SHA256_PAYLOAD(3), + STREAMING_AWS4_HMAC_SHA256_EVENTS(4); + + AwsSignedBodyValueType(int nativeValue) { + this.nativeValue = nativeValue; + } + + public int getNativeValue() { return nativeValue; } + + public static AwsSignedBodyValueType getEnumValueFromInteger(int value) { + AwsSignedBodyValueType enumValue = enumMapping.get(value); + if (enumValue != null) { + return enumValue; + } + + throw new RuntimeException("Illegal signed body value type value in signing configuration"); + } + + private static Map buildEnumMapping() { + Map enumMapping = new HashMap(); + enumMapping.put(EMPTY.getNativeValue(), EMPTY); + enumMapping.put(PAYLOAD.getNativeValue(), PAYLOAD); + enumMapping.put(UNSIGNED_PAYLOAD.getNativeValue(), UNSIGNED_PAYLOAD); + enumMapping.put(STREAMING_AWS4_HMAC_SHA256_PAYLOAD.getNativeValue(), STREAMING_AWS4_HMAC_SHA256_PAYLOAD); + enumMapping.put(STREAMING_AWS4_HMAC_SHA256_EVENTS.getNativeValue(), STREAMING_AWS4_HMAC_SHA256_EVENTS); + + return enumMapping; + } + + private int nativeValue; + + private static Map enumMapping = buildEnumMapping(); + } + + public enum AwsSignedBodyHeaderType { + NONE(0), + X_AMZ_CONTENT_SHA256(1); + + AwsSignedBodyHeaderType(int nativeValue) { + this.nativeValue = nativeValue; + } + + public int getNativeValue() { return nativeValue; } + + public static AwsSignedBodyHeaderType getEnumValueFromInteger(int value) { + AwsSignedBodyHeaderType enumValue = enumMapping.get(value); + if (enumValue != null) { + return enumValue; + } + + throw new RuntimeException("Illegal signed body header value in signing configuration"); + } + + private static Map buildEnumMapping() { + Map enumMapping = new HashMap(); + enumMapping.put(NONE.getNativeValue(), NONE); + enumMapping.put(X_AMZ_CONTENT_SHA256.getNativeValue(), X_AMZ_CONTENT_SHA256); + + return enumMapping; + } + + private int nativeValue; + + private static Map enumMapping = buildEnumMapping(); + } + + private int algorithm = AwsSigningAlgorithm.SIGV4.getNativeValue(); + private int signatureType = AwsSignatureType.HTTP_REQUEST_VIA_HEADERS.getNativeValue(); private String region; private String service; private long time = System.currentTimeMillis(); private CredentialsProvider credentialsProvider; - private Predicate shouldSignParameter; + private Credentials credentials; + private Predicate shouldSignHeader; private boolean useDoubleUriEncode = true; private boolean shouldNormalizeUriPath = true; - private int signBody = AwsBodySigningConfigType.AWS_BODY_SIGNING_OFF.getNativeValue(); + private boolean omitSessionToken = false; + private int signedBodyValue = AwsSignedBodyValueType.PAYLOAD.getNativeValue(); + private int signedBodyHeader = AwsSignedBodyHeaderType.NONE.getNativeValue(); + private long expirationInSeconds = 0; public AwsSigningConfig() {} public AwsSigningConfig clone() { try (AwsSigningConfig clone = new AwsSigningConfig()) { - clone.setSigningAlgorithm(getSigningAlgorithm()); + clone.setAlgorithm(getAlgorithm()); + clone.setSignatureType(getSignatureType()); clone.setRegion(getRegion()); clone.setService(getService()); clone.setTime(getTime()); clone.setCredentialsProvider(getCredentialsProvider()); - clone.setShouldSignParameter(getShouldSignParameter()); + clone.setCredentials(getCredentials()); + clone.setShouldSignHeader(getShouldSignHeader()); clone.setUseDoubleUriEncode(getUseDoubleUriEncode()); clone.setShouldNormalizeUriPath(getShouldNormalizeUriPath()); - clone.setSignBody(getSignBody()); + clone.setOmitSessionToken(getOmitSessionToken()); + clone.setSignedBodyValue(getSignedBodyValue()); + clone.setSignedBodyHeader(getSignedBodyHeader()); + clone.setExpirationInSeconds(getExpirationInSeconds()); // success, bump up the ref count so we can escape the try-with-resources block clone.addRef(); @@ -137,9 +218,14 @@ protected void releaseNativeHandle() {} @Override protected boolean canReleaseReferencesImmediately() { return true; } - public void setSigningAlgorithm(AwsSigningAlgorithm algorithm) { this.signingAlgorithm = algorithm.getNativeValue(); } - public AwsSigningAlgorithm getSigningAlgorithm() { - return AwsSigningAlgorithm.getEnumValueFromInteger(signingAlgorithm); + public void setAlgorithm(AwsSigningAlgorithm algorithm) { this.algorithm = algorithm.getNativeValue(); } + public AwsSigningAlgorithm getAlgorithm() { + return AwsSigningAlgorithm.getEnumValueFromInteger(algorithm); + } + + public void setSignatureType(AwsSignatureType signatureType) { this.signatureType = signatureType.getNativeValue(); } + public AwsSignatureType getSignatureType() { + return AwsSignatureType.getEnumValueFromInteger(signatureType); } public void setRegion(String region) { this.region = region; } @@ -158,8 +244,11 @@ public void setCredentialsProvider(CredentialsProvider credentialsProvider) { public CredentialsProvider getCredentialsProvider() { return credentialsProvider; } - public void setShouldSignParameter(Predicate shouldSignParameter) { this.shouldSignParameter = shouldSignParameter; } - public Predicate getShouldSignParameter() { return shouldSignParameter; } + public void setCredentials(Credentials credentials) { this.credentials = credentials; } + public Credentials getCredentials() { return credentials; } + + public void setShouldSignHeader(Predicate shouldSignHeader) { this.shouldSignHeader = shouldSignHeader; } + public Predicate getShouldSignHeader() { return shouldSignHeader; } public void setUseDoubleUriEncode(boolean useDoubleUriEncode) { this.useDoubleUriEncode = useDoubleUriEncode; } public boolean getUseDoubleUriEncode() { return useDoubleUriEncode; } @@ -167,8 +256,17 @@ public void setCredentialsProvider(CredentialsProvider credentialsProvider) { public void setShouldNormalizeUriPath(boolean shouldNormalizeUriPath) { this.shouldNormalizeUriPath = shouldNormalizeUriPath; } public boolean getShouldNormalizeUriPath() { return shouldNormalizeUriPath; } - public void setSignBody(AwsBodySigningConfigType signBody) { this.signBody = signBody.getNativeValue(); } - public AwsBodySigningConfigType getSignBody() { return AwsBodySigningConfigType.getEnumValueFromInteger(signBody); } + public void setOmitSessionToken(boolean omitSessionToken) { this.omitSessionToken = omitSessionToken; } + public boolean getOmitSessionToken() { return omitSessionToken; } + + public void setSignedBodyValue(AwsSignedBodyValueType signedBodyValue) { this.signedBodyValue = signedBodyValue.getNativeValue(); } + public AwsSignedBodyValueType getSignedBodyValue() { return AwsSignedBodyValueType.getEnumValueFromInteger(signedBodyValue); } + + public void setSignedBodyHeader(AwsSignedBodyHeaderType signedBodyHeader) { this.signedBodyHeader = signedBodyHeader.getNativeValue(); } + public AwsSignedBodyHeaderType getSignedBodyHeader() { return AwsSignedBodyHeaderType.getEnumValueFromInteger(signedBodyHeader); } + + public void setExpirationInSeconds(long expirationInSeconds) { this.expirationInSeconds = expirationInSeconds; } + public long getExpirationInSeconds() { return expirationInSeconds; } } diff --git a/src/native/aws_signing.c b/src/native/aws_signing.c index 1af4d29f8..1165413e7 100644 --- a/src/native/aws_signing.c +++ b/src/native/aws_signing.c @@ -14,6 +14,8 @@ */ #include "crt.h" + +#include "credentials.h" #include "http_request_utils.h" #include "java_class_ids.h" @@ -23,6 +25,7 @@ #include #include #include +#include #include #include @@ -42,11 +45,12 @@ struct s_aws_sign_request_callback_data { JavaVM *jvm; jobject java_future; jobject java_original_request; - jobject java_sign_param_predicate; + jobject java_sign_header_predicate; struct aws_http_message *native_request; struct aws_signable *original_message_signable; struct aws_string *region; struct aws_string *service; + struct aws_credentials *credentials; }; static void s_cleanup_callback_data(struct s_aws_sign_request_callback_data *callback_data) { @@ -56,8 +60,8 @@ static void s_cleanup_callback_data(struct s_aws_sign_request_callback_data *cal (*env)->DeleteGlobalRef(env, callback_data->java_future); (*env)->DeleteGlobalRef(env, callback_data->java_original_request); - if (callback_data->java_sign_param_predicate) { - (*env)->DeleteGlobalRef(env, callback_data->java_sign_param_predicate); + if (callback_data->java_sign_header_predicate) { + (*env)->DeleteGlobalRef(env, callback_data->java_sign_header_predicate); } if (callback_data->native_request) { @@ -68,6 +72,10 @@ static void s_cleanup_callback_data(struct s_aws_sign_request_callback_data *cal aws_signable_destroy(callback_data->original_message_signable); } + if (callback_data->credentials) { + aws_credentials_release(callback_data->credentials); + } + aws_string_destroy(callback_data->region); aws_string_destroy(callback_data->service); @@ -154,19 +162,17 @@ static void s_aws_signing_complete(struct aws_signing_result *result, int error_ s_cleanup_callback_data(callback_data); } -static bool s_should_sign_param(const struct aws_byte_cursor *name, void *user_data) { - (void)name; - +static bool s_should_sign_header(const struct aws_byte_cursor *name, void *user_data) { struct s_aws_sign_request_callback_data *callback_data = user_data; JNIEnv *env = aws_jni_get_thread_env(callback_data->jvm); - jstring parameter_name = aws_jni_string_from_cursor(env, name); + jstring header_name = aws_jni_string_from_cursor(env, name); bool result = (*env)->CallBooleanMethod( - env, callback_data->java_sign_param_predicate, predicate_properties.test_method_id, (jobject)parameter_name); + env, callback_data->java_sign_header_predicate, predicate_properties.test_method_id, (jobject)header_name); - (*env)->DeleteLocalRef(env, parameter_name); + (*env)->DeleteLocalRef(env, header_name); AWS_FATAL_ASSERT(!(*env)->ExceptionCheck(env)); @@ -185,6 +191,8 @@ static int s_build_signing_config( config->config_type = AWS_SIGNING_CONFIG_AWS; config->algorithm = (enum aws_signing_algorithm)(*env)->GetIntField( env, java_config, aws_signing_config_properties.algorithm_field_id); + config->signature_type = (enum aws_signature_type)(*env)->GetIntField( + env, java_config, aws_signing_config_properties.signature_type_field_id); jstring region = (jstring)(*env)->GetObjectField(env, java_config, aws_signing_config_properties.region_field_id); callback_data->region = aws_jni_new_string_from_jstring(env, region); @@ -197,26 +205,43 @@ static int s_build_signing_config( int64_t epoch_time_millis = (*env)->GetLongField(env, java_config, aws_signing_config_properties.time_field_id); aws_date_time_init_epoch_millis(&config->date, (uint64_t)epoch_time_millis); - jobject sign_param_predicate = - (*env)->GetObjectField(env, java_config, aws_signing_config_properties.should_sign_parameter_field_id); - if (sign_param_predicate != NULL) { - callback_data->java_sign_param_predicate = (*env)->NewGlobalRef(env, sign_param_predicate); - AWS_FATAL_ASSERT(callback_data->java_sign_param_predicate != NULL); + jobject sign_header_predicate = + (*env)->GetObjectField(env, java_config, aws_signing_config_properties.should_sign_header_field_id); + if (sign_header_predicate != NULL) { + callback_data->java_sign_header_predicate = (*env)->NewGlobalRef(env, sign_header_predicate); + AWS_FATAL_ASSERT(callback_data->java_sign_header_predicate != NULL); - config->should_sign_param = s_should_sign_param; - config->should_sign_param_ud = callback_data; + config->should_sign_header = s_should_sign_header; + config->should_sign_header_ud = callback_data; } - config->use_double_uri_encode = + config->flags.use_double_uri_encode = (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.use_double_uri_encode_field_id); - config->should_normalize_uri_path = + config->flags.should_normalize_uri_path = (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.should_normalize_uri_path_field_id); - config->body_signing_type = (*env)->GetIntField(env, java_config, aws_signing_config_properties.sign_body_field_id); + config->flags.omit_session_token = + (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.omit_session_token_field_id); + + config->signed_body_value = + (*env)->GetIntField(env, java_config, aws_signing_config_properties.signed_body_value_field_id); + config->signed_body_header = + (*env)->GetIntField(env, java_config, aws_signing_config_properties.signed_body_header_field_id); jobject provider = (*env)->GetObjectField(env, java_config, aws_signing_config_properties.credentials_provider_field_id); - config->credentials_provider = - (void *)(*env)->CallLongMethod(env, provider, crt_resource_properties.get_native_handle_method_id); + if (provider != NULL) { + config->credentials_provider = + (void *)(*env)->CallLongMethod(env, provider, crt_resource_properties.get_native_handle_method_id); + } + + jobject credentials = (*env)->GetObjectField(env, java_config, aws_signing_config_properties.credentials_field_id); + if (credentials != NULL) { + callback_data->credentials = aws_credentials_new_from_java_credentials(env, credentials); + config->credentials = callback_data->credentials; + } + + config->expiration_in_seconds = + (uint64_t)(*env)->GetLongField(env, java_config, aws_signing_config_properties.expiration_in_seconds_field_id); if ((*env)->ExceptionCheck(env)) { return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE); @@ -259,9 +284,8 @@ void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSig AWS_ZERO_STRUCT(signing_config); if (s_build_signing_config(env, callback_data, java_signing_config, &signing_config)) { - aws_jni_throw_runtime_exception(env, "Failed to allocated sign request callback data"); - s_cleanup_callback_data(callback_data); - return; + aws_jni_throw_runtime_exception(env, "Failed to create signing configuration"); + goto on_error; } jobject java_http_request_body_stream = @@ -271,15 +295,13 @@ void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSig aws_http_request_new_from_java_http_request(env, marshalled_request, java_http_request_body_stream); if (callback_data->native_request == NULL) { aws_jni_throw_runtime_exception(env, "Failed to create native http request from Java HttpRequest"); - s_cleanup_callback_data(callback_data); - return; + goto on_error; } callback_data->original_message_signable = aws_signable_new_http_request(allocator, callback_data->native_request); if (callback_data->original_message_signable == NULL) { aws_jni_throw_runtime_exception(env, "Failed to create signable from http request"); - s_cleanup_callback_data(callback_data); - return; + goto on_error; } /* Sign the native request */ @@ -290,8 +312,14 @@ void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSig s_aws_signing_complete, callback_data)) { aws_jni_throw_runtime_exception(env, "Failed to initiate signing process for HttpRequest"); - s_cleanup_callback_data(callback_data); + goto on_error; } + + return; + +on_error: + + s_cleanup_callback_data(callback_data); } #if UINTPTR_MAX == 0xffffffff diff --git a/src/native/credentials.c b/src/native/credentials.c new file mode 100644 index 000000000..e580ac12f --- /dev/null +++ b/src/native/credentials.c @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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 "crt.h" +#include "java_class_ids.h" + +#include + +/* on 32-bit platforms, casting pointers to longs throws a warning we don't need */ +#if UINTPTR_MAX == 0xffffffff +# if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */ +# else +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpointer-to-int-cast" +# pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +# endif +#endif + +struct aws_credentials *aws_credentials_new_from_java_credentials(JNIEnv *env, jobject java_credentials) { + if (java_credentials == NULL) { + return NULL; + } + + jbyteArray access_key_id = + (*env)->GetObjectField(env, java_credentials, credentials_properties.access_key_id_field_id); + jbyteArray secret_access_key = + (*env)->GetObjectField(env, java_credentials, credentials_properties.secret_access_key_field_id); + jbyteArray session_token = + (*env)->GetObjectField(env, java_credentials, credentials_properties.session_token_field_id); + + if (access_key_id == NULL || secret_access_key == NULL) { + return NULL; + } + + struct aws_credentials *credentials = NULL; + + struct aws_byte_cursor access_key_id_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, access_key_id); + struct aws_byte_cursor secret_access_key_cursor = + aws_jni_byte_cursor_from_jbyteArray_acquire(env, secret_access_key); + + struct aws_byte_cursor session_token_cursor; + AWS_ZERO_STRUCT(session_token_cursor); + if (session_token != NULL) { + session_token_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, session_token); + } + + credentials = aws_credentials_new( + aws_jni_get_allocator(), access_key_id_cursor, secret_access_key_cursor, session_token_cursor, UINT64_MAX); + + aws_jni_byte_cursor_from_jbyteArray_release(env, access_key_id, access_key_id_cursor); + aws_jni_byte_cursor_from_jbyteArray_release(env, secret_access_key, secret_access_key_cursor); + if (session_token != NULL) { + aws_jni_byte_cursor_from_jbyteArray_release(env, session_token, session_token_cursor); + } + + return credentials; +} + +#if UINTPTR_MAX == 0xffffffff +# if defined(_MSC_VER) +# pragma warning(pop) +# else +# pragma GCC diagnostic pop +# endif +#endif diff --git a/src/native/credentials.h b/src/native/credentials.h new file mode 100644 index 000000000..12803f0b6 --- /dev/null +++ b/src/native/credentials.h @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +#ifndef AWS_JNI_CRT_CREDENTIALS_H +#define AWS_JNI_CRT_CREDENTIALS_H + +#include + +struct aws_credentials; + +struct aws_credentials *aws_credentials_new_from_java_credentials(JNIEnv *env, jobject java_credentials); + +#endif /* AWS_JNI_CRT_CREDENTIALS_H */ diff --git a/src/native/credentials_provider.c b/src/native/credentials_provider.c index 07a3e4e93..34ecbe7ee 100644 --- a/src/native/credentials_provider.c +++ b/src/native/credentials_provider.c @@ -257,7 +257,8 @@ struct aws_credentials_provider_get_credentials_callback_data { jobject java_credentials_future; }; -static void s_on_get_credentials_callback(struct aws_credentials *credentials, void *user_data) { +static void s_on_get_credentials_callback(struct aws_credentials *credentials, int error_code, void *user_data) { + (void)error_code; struct aws_credentials_provider_get_credentials_callback_data *callback_data = user_data; JNIEnv *env = aws_jni_get_thread_env(callback_data->jvm); @@ -271,15 +272,14 @@ static void s_on_get_credentials_callback(struct aws_credentials *credentials, v java_credentials = (*env)->NewObject( env, credentials_properties.credentials_class, credentials_properties.constructor_method_id); if (java_credentials != NULL) { - struct aws_byte_cursor access_key_id_cursor = aws_byte_cursor_from_string(credentials->access_key_id); + struct aws_byte_cursor access_key_id_cursor = aws_credentials_get_access_key_id(credentials); access_key_id = aws_jni_byte_array_from_cursor(env, &access_key_id_cursor); - struct aws_byte_cursor secret_access_key_cursor = - aws_byte_cursor_from_string(credentials->secret_access_key); + struct aws_byte_cursor secret_access_key_cursor = aws_credentials_get_secret_access_key(credentials); secret_access_key = aws_jni_byte_array_from_cursor(env, &secret_access_key_cursor); - if (credentials->session_token != NULL) { - struct aws_byte_cursor session_token_cursor = aws_byte_cursor_from_string(credentials->session_token); + struct aws_byte_cursor session_token_cursor = aws_credentials_get_session_token(credentials); + if (session_token_cursor.len > 0) { session_token = aws_jni_byte_array_from_cursor(env, &session_token_cursor); } diff --git a/src/native/java_class_ids.c b/src/native/java_class_ids.c index 8fa5ef60c..ab55bb97f 100644 --- a/src/native/java_class_ids.c +++ b/src/native/java_class_ids.c @@ -40,9 +40,13 @@ static void s_cache_aws_signing_config(JNIEnv *env) { aws_signing_config_properties.aws_signing_config_class = (*env)->NewGlobalRef(env, aws_signing_config_class); aws_signing_config_properties.algorithm_field_id = - (*env)->GetFieldID(env, aws_signing_config_class, "signingAlgorithm", "I"); + (*env)->GetFieldID(env, aws_signing_config_class, "algorithm", "I"); AWS_FATAL_ASSERT(aws_signing_config_properties.algorithm_field_id); + aws_signing_config_properties.signature_type_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "signatureType", "I"); + AWS_FATAL_ASSERT(aws_signing_config_properties.signature_type_field_id); + aws_signing_config_properties.region_field_id = (*env)->GetFieldID(env, aws_signing_config_class, "region", "Ljava/lang/String;"); AWS_FATAL_ASSERT(aws_signing_config_properties.region_field_id); @@ -61,9 +65,13 @@ static void s_cache_aws_signing_config(JNIEnv *env) { "Lsoftware/amazon/awssdk/crt/auth/credentials/CredentialsProvider;"); AWS_FATAL_ASSERT(aws_signing_config_properties.credentials_provider_field_id); - aws_signing_config_properties.should_sign_parameter_field_id = - (*env)->GetFieldID(env, aws_signing_config_class, "shouldSignParameter", "Ljava/util/function/Predicate;"); - AWS_FATAL_ASSERT(aws_signing_config_properties.should_sign_parameter_field_id); + aws_signing_config_properties.credentials_field_id = (*env)->GetFieldID( + env, aws_signing_config_class, "credentials", "Lsoftware/amazon/awssdk/crt/auth/credentials/Credentials;"); + AWS_FATAL_ASSERT(aws_signing_config_properties.credentials_field_id); + + aws_signing_config_properties.should_sign_header_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "shouldSignHeader", "Ljava/util/function/Predicate;"); + AWS_FATAL_ASSERT(aws_signing_config_properties.should_sign_header_field_id); aws_signing_config_properties.use_double_uri_encode_field_id = (*env)->GetFieldID(env, aws_signing_config_class, "useDoubleUriEncode", "Z"); @@ -73,9 +81,21 @@ static void s_cache_aws_signing_config(JNIEnv *env) { (*env)->GetFieldID(env, aws_signing_config_class, "shouldNormalizeUriPath", "Z"); AWS_FATAL_ASSERT(aws_signing_config_properties.should_normalize_uri_path_field_id); - aws_signing_config_properties.sign_body_field_id = - (*env)->GetFieldID(env, aws_signing_config_class, "signBody", "I"); - AWS_FATAL_ASSERT(aws_signing_config_properties.sign_body_field_id); + aws_signing_config_properties.omit_session_token_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "omitSessionToken", "Z"); + AWS_FATAL_ASSERT(aws_signing_config_properties.omit_session_token_field_id); + + aws_signing_config_properties.signed_body_value_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "signedBodyValue", "I"); + AWS_FATAL_ASSERT(aws_signing_config_properties.signed_body_value_field_id); + + aws_signing_config_properties.signed_body_header_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "signedBodyHeader", "I"); + AWS_FATAL_ASSERT(aws_signing_config_properties.signed_body_header_field_id); + + aws_signing_config_properties.expiration_in_seconds_field_id = + (*env)->GetFieldID(env, aws_signing_config_class, "expirationInSeconds", "J"); + AWS_FATAL_ASSERT(aws_signing_config_properties.expiration_in_seconds_field_id); } struct java_predicate_properties predicate_properties; diff --git a/src/native/java_class_ids.h b/src/native/java_class_ids.h index a59f95564..3cdbc77fd 100644 --- a/src/native/java_class_ids.h +++ b/src/native/java_class_ids.h @@ -29,14 +29,19 @@ extern struct java_http_request_body_stream_properties http_request_body_stream_ struct java_aws_signing_config_properties { jclass aws_signing_config_class; jfieldID algorithm_field_id; + jfieldID signature_type_field_id; jfieldID region_field_id; jfieldID service_field_id; jfieldID time_field_id; + jfieldID credentials_field_id; jfieldID credentials_provider_field_id; - jfieldID should_sign_parameter_field_id; + jfieldID should_sign_header_field_id; jfieldID use_double_uri_encode_field_id; jfieldID should_normalize_uri_path_field_id; - jfieldID sign_body_field_id; + jfieldID omit_session_token_field_id; + jfieldID signed_body_value_field_id; + jfieldID signed_body_header_field_id; + jfieldID expiration_in_seconds_field_id; }; extern struct java_aws_signing_config_properties aws_signing_config_properties; diff --git a/src/test/java/software/amazon/awssdk/crt/test/SigningTest.java b/src/test/java/software/amazon/awssdk/crt/test/SigningTest.java index 9f5ae27c3..067c34392 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/SigningTest.java +++ b/src/test/java/software/amazon/awssdk/crt/test/SigningTest.java @@ -28,6 +28,7 @@ import static org.junit.Assert.assertTrue; import software.amazon.awssdk.crt.*; +import software.amazon.awssdk.crt.auth.credentials.Credentials; import software.amazon.awssdk.crt.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.crt.auth.signing.AwsSigner; import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; @@ -38,8 +39,11 @@ public class SigningTest extends CrtTestFixture { - public static String METHOD = "POST"; - public static SimpleDateFormat DATE_FORMAT = dateFormat(); + private static String METHOD = "POST"; + private static byte[] TEST_ACCESS_KEY_ID = "AKIDEXAMPLE".getBytes(); + private static byte[] TEST_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY".getBytes(); + + private static SimpleDateFormat DATE_FORMAT = dateFormat(); private static SimpleDateFormat dateFormat() { final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); @@ -122,12 +126,11 @@ private boolean hasHeaderWithValue(HttpRequest request, String name, String valu return false; } - @Test public void testSigningSuccess() throws Exception { try (StaticCredentialsProvider provider = new StaticCredentialsProvider.StaticCredentialsProviderBuilder() - .withAccessKeyId("AKIDEXAMPLE".getBytes()) - .withSecretAccessKey("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY".getBytes()) + .withAccessKeyId(TEST_ACCESS_KEY_ID) + .withSecretAccessKey(TEST_SECRET_ACCESS_KEY) .build();) { HttpRequest request = createSimpleRequest("https://www.example.com", "POST", "/derp", "Hello"); @@ -135,15 +138,16 @@ public void testSigningSuccess() throws Exception { Predicate filterParam = param -> !param.equals("bad-param"); try (AwsSigningConfig config = new AwsSigningConfig()) { - config.setSigningAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4_HEADER); + config.setAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4); + config.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_HEADERS); config.setRegion("us-east-1"); config.setService("service"); config.setTime(System.currentTimeMillis()); config.setCredentialsProvider(provider); - config.setShouldSignParameter(filterParam); + config.setShouldSignHeader(filterParam); config.setUseDoubleUriEncode(true); config.setShouldNormalizeUriPath(true); - config.setSignBody(AwsSigningConfig.AwsBodySigningConfigType.AWS_BODY_SIGNING_OFF); + config.setSignedBodyValue(AwsSigningConfig.AwsSignedBodyValueType.EMPTY); CompletableFuture result = AwsSigner.signRequest(request, config); HttpRequest signedRequest = result.get(); @@ -158,21 +162,23 @@ public void testSigningSuccess() throws Exception { @Test public void testQuerySigningSuccess() throws Exception { try (StaticCredentialsProvider provider = new StaticCredentialsProvider.StaticCredentialsProviderBuilder() - .withAccessKeyId("AKIDEXAMPLE".getBytes()) - .withSecretAccessKey("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY".getBytes()) + .withAccessKeyId(TEST_ACCESS_KEY_ID) + .withSecretAccessKey(TEST_SECRET_ACCESS_KEY) .build();) { HttpRequest request = createSigv4TestSuiteRequest(); try (AwsSigningConfig config = new AwsSigningConfig()) { - config.setSigningAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4_QUERY_PARAM); + config.setAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4); + config.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS); config.setRegion("us-east-1"); config.setService("service"); config.setTime(DATE_FORMAT.parse("2015-08-30T12:36:00Z").getTime()); config.setCredentialsProvider(provider); config.setUseDoubleUriEncode(true); config.setShouldNormalizeUriPath(true); - config.setSignBody(AwsSigningConfig.AwsBodySigningConfigType.AWS_BODY_SIGNING_OFF); + config.setSignedBodyValue(AwsSigningConfig.AwsSignedBodyValueType.EMPTY); + config.setExpirationInSeconds(60); CompletableFuture result = AwsSigner.signRequest(request, config); HttpRequest signedRequest = result.get(); @@ -184,6 +190,7 @@ public void testQuerySigningSuccess() throws Exception { assertTrue(path.contains("X-Amz-SignedHeaders=host")); assertTrue(path.contains("X-Amz-Credential=AKIDEXAMPLE%2F20150830%2F")); assertTrue(path.contains("X-Amz-Algorithm=AWS4-HMAC-SHA256")); + assertTrue(path.contains("X-Amz-Expires=60")); } } } @@ -191,23 +198,22 @@ public void testQuerySigningSuccess() throws Exception { @Test public void testSigningBasicSigv4Test() throws Exception { try (StaticCredentialsProvider provider = new StaticCredentialsProvider.StaticCredentialsProviderBuilder() - .withAccessKeyId("AKIDEXAMPLE".getBytes()) - .withSecretAccessKey("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY".getBytes()) + .withAccessKeyId(TEST_ACCESS_KEY_ID) + .withSecretAccessKey(TEST_SECRET_ACCESS_KEY) .build();) { HttpRequest request = createSigv4TestSuiteRequest(); - Predicate filterParam = param -> !param.equals("bad-param"); - try (AwsSigningConfig config = new AwsSigningConfig()) { - config.setSigningAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4_HEADER); + config.setAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4); + config.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_HEADERS); config.setRegion("us-east-1"); config.setService("service"); config.setTime(DATE_FORMAT.parse("2015-08-30T12:36:00Z").getTime()); config.setCredentialsProvider(provider); config.setUseDoubleUriEncode(true); config.setShouldNormalizeUriPath(true); - config.setSignBody(AwsSigningConfig.AwsBodySigningConfigType.AWS_BODY_SIGNING_OFF); + config.setSignedBodyValue(AwsSigningConfig.AwsSignedBodyValueType.EMPTY); CompletableFuture result = AwsSigner.signRequest(request, config); HttpRequest signedRequest = result.get(); @@ -224,22 +230,23 @@ public void testSigningBasicSigv4Test() throws Exception { @Test(expected = CrtRuntimeException.class) public void testSigningFailureBadRequest() throws Exception { try (StaticCredentialsProvider provider = new StaticCredentialsProvider.StaticCredentialsProviderBuilder() - .withAccessKeyId("AKIDEXAMPLE".getBytes()) - .withSecretAccessKey("wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY".getBytes()) + .withAccessKeyId(TEST_ACCESS_KEY_ID) + .withSecretAccessKey(TEST_SECRET_ACCESS_KEY) .build();) { // request is missing Host header HttpRequest request = createUnsignableRequest("POST", "/bad"); try (AwsSigningConfig config = new AwsSigningConfig()) { - config.setSigningAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4_HEADER); + config.setAlgorithm(AwsSigningConfig.AwsSigningAlgorithm.SIGV4); + config.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_HEADERS); config.setRegion("us-east-1"); config.setService("service"); config.setTime(System.currentTimeMillis()); config.setCredentialsProvider(provider); config.setUseDoubleUriEncode(true); config.setShouldNormalizeUriPath(true); - config.setSignBody(AwsSigningConfig.AwsBodySigningConfigType.AWS_BODY_SIGNING_OFF); + config.setSignedBodyValue(AwsSigningConfig.AwsSignedBodyValueType.EMPTY); CompletableFuture result = AwsSigner.signRequest(request, config); result.get(); @@ -253,6 +260,4 @@ public void testSigningFailureBadRequest() throws Exception { throw crt; } } - - };