xref: /aosp_15_r20/external/aws-crt-java/src/native/credentials_provider.c (revision 3c7ae9de214676c52d19f01067dc1a404272dc11)
1 /**
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  * SPDX-License-Identifier: Apache-2.0.
4  */
5 
6 #include "credentials.h"
7 #include "crt.h"
8 #include "http_connection_manager.h"
9 #include "java_class_ids.h"
10 
11 #include <http_proxy_options.h>
12 #include <jni.h>
13 #include <string.h>
14 
15 #include <aws/auth/credentials.h>
16 #include <aws/common/clock.h>
17 #include <aws/common/string.h>
18 #include <aws/http/connection.h>
19 #include <aws/http/proxy.h>
20 #include <aws/io/tls_channel_handler.h>
21 
22 /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
23 #if UINTPTR_MAX == 0xffffffff
24 #    if defined(_MSC_VER)
25 #        pragma warning(push)
26 #        pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
27 #    else
28 #        pragma GCC diagnostic push
29 #        pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
30 #        pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
31 #    endif
32 #endif
33 
34 struct aws_credentials_provider_callback_data {
35     JavaVM *jvm;
36     struct aws_credentials_provider *provider;
37     jweak java_crt_credentials_provider;
38 
39     jobject jni_delegate_credential_handler;
40 };
41 
s_callback_data_clean_up(JNIEnv * env,struct aws_allocator * allocator,struct aws_credentials_provider_callback_data * callback_data)42 static void s_callback_data_clean_up(
43     JNIEnv *env,
44     struct aws_allocator *allocator,
45     struct aws_credentials_provider_callback_data *callback_data) {
46 
47     (*env)->DeleteWeakGlobalRef(env, callback_data->java_crt_credentials_provider);
48     if (callback_data->jni_delegate_credential_handler != NULL) {
49         (*env)->DeleteGlobalRef(env, callback_data->jni_delegate_credential_handler);
50     }
51 
52     aws_mem_release(allocator, callback_data);
53 }
54 
s_on_shutdown_complete(void * user_data)55 static void s_on_shutdown_complete(void *user_data) {
56     struct aws_credentials_provider_callback_data *callback_data = user_data;
57 
58     AWS_LOGF_DEBUG(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Credentials providers shutdown complete");
59 
60     // Tell the Java credentials providers that shutdown is done.  This lets it release its references.
61     /********** JNI ENV ACQUIRE **********/
62     JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
63     if (env == NULL) {
64         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
65         return;
66     }
67 
68     jobject java_crt_credentials_provider = (*env)->NewLocalRef(env, callback_data->java_crt_credentials_provider);
69     if (java_crt_credentials_provider != NULL) {
70         (*env)->CallVoidMethod(
71             env, java_crt_credentials_provider, credentials_provider_properties.on_shutdown_complete_method_id);
72 
73         (*env)->DeleteLocalRef(env, java_crt_credentials_provider);
74         AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
75     }
76 
77     struct aws_allocator *allocator = aws_jni_get_allocator();
78     // We're done with this callback data, clean it up.
79 
80     JavaVM *jvm = callback_data->jvm;
81     s_callback_data_clean_up(env, allocator, callback_data);
82 
83     aws_jni_release_thread_env(jvm, env);
84     /********** JNI ENV RELEASE **********/
85 }
86 
87 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_StaticCredentialsProvider_staticCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jbyteArray access_key_id,jbyteArray secret_access_key,jbyteArray session_token)88     Java_software_amazon_awssdk_crt_auth_credentials_StaticCredentialsProvider_staticCredentialsProviderNew(
89         JNIEnv *env,
90         jclass jni_class,
91         jobject java_crt_credentials_provider,
92         jbyteArray access_key_id,
93         jbyteArray secret_access_key,
94         jbyteArray session_token) {
95 
96     (void)jni_class;
97     aws_cache_jni_ids(env);
98 
99     struct aws_allocator *allocator = aws_jni_get_allocator();
100 
101     struct aws_credentials_provider_callback_data *callback_data =
102         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
103     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
104 
105     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
106     AWS_FATAL_ASSERT(jvmresult == 0);
107 
108     struct aws_credentials_provider_static_options options;
109     AWS_ZERO_STRUCT(options);
110     options.access_key_id = aws_jni_byte_cursor_from_jbyteArray_acquire(env, access_key_id);
111     options.secret_access_key = aws_jni_byte_cursor_from_jbyteArray_acquire(env, secret_access_key);
112     if (session_token) {
113         options.session_token = aws_jni_byte_cursor_from_jbyteArray_acquire(env, session_token);
114     }
115     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
116     options.shutdown_options.shutdown_user_data = callback_data;
117 
118     struct aws_credentials_provider *provider = aws_credentials_provider_new_static(allocator, &options);
119     if (provider == NULL) {
120         s_callback_data_clean_up(env, allocator, callback_data);
121         aws_jni_throw_runtime_exception(env, "Failed to create static credentials provider");
122     } else {
123         callback_data->provider = provider;
124     }
125 
126     aws_jni_byte_cursor_from_jbyteArray_release(env, access_key_id, options.access_key_id);
127     aws_jni_byte_cursor_from_jbyteArray_release(env, secret_access_key, options.secret_access_key);
128 
129     if (session_token) {
130         aws_jni_byte_cursor_from_jbyteArray_release(env, session_token, options.session_token);
131     }
132 
133     return (jlong)provider;
134 }
135 
136 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_DefaultChainCredentialsProvider_defaultChainCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrapHandle)137     Java_software_amazon_awssdk_crt_auth_credentials_DefaultChainCredentialsProvider_defaultChainCredentialsProviderNew(
138         JNIEnv *env,
139         jclass jni_class,
140         jobject java_crt_credentials_provider,
141         jlong bootstrapHandle) {
142 
143     (void)jni_class;
144     (void)env;
145     aws_cache_jni_ids(env);
146 
147     struct aws_allocator *allocator = aws_jni_get_allocator();
148     struct aws_credentials_provider_callback_data *callback_data =
149         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
150     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
151 
152     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
153     AWS_FATAL_ASSERT(jvmresult == 0);
154 
155     struct aws_credentials_provider_chain_default_options options;
156     AWS_ZERO_STRUCT(options);
157     options.bootstrap = (struct aws_client_bootstrap *)bootstrapHandle;
158     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
159     options.shutdown_options.shutdown_user_data = callback_data;
160 
161     struct aws_credentials_provider *provider = aws_credentials_provider_new_chain_default(allocator, &options);
162     if (provider == NULL) {
163         s_callback_data_clean_up(env, allocator, callback_data);
164         aws_jni_throw_runtime_exception(env, "Failed to create default credentials provider chain");
165     } else {
166         callback_data->provider = provider;
167     }
168 
169     return (jlong)provider;
170 }
171 
172 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_ProfileCredentialsProvider_profileCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrapHandle,jlong tls_context_handle,jbyteArray profile_name_override,jbyteArray config_file_name_override,jbyteArray credentials_file_name_override)173     Java_software_amazon_awssdk_crt_auth_credentials_ProfileCredentialsProvider_profileCredentialsProviderNew(
174         JNIEnv *env,
175         jclass jni_class,
176         jobject java_crt_credentials_provider,
177         jlong bootstrapHandle,
178         jlong tls_context_handle,
179         jbyteArray profile_name_override,
180         jbyteArray config_file_name_override,
181         jbyteArray credentials_file_name_override) {
182 
183     (void)jni_class;
184     (void)env;
185     aws_cache_jni_ids(env);
186 
187     struct aws_allocator *allocator = aws_jni_get_allocator();
188     struct aws_credentials_provider_callback_data *callback_data =
189         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
190     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
191 
192     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
193     AWS_FATAL_ASSERT(jvmresult == 0);
194 
195     struct aws_credentials_provider_profile_options options;
196     AWS_ZERO_STRUCT(options);
197     options.bootstrap = (struct aws_client_bootstrap *)bootstrapHandle;
198     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
199     options.shutdown_options.shutdown_user_data = callback_data;
200     options.tls_ctx = (struct aws_tls_ctx *)tls_context_handle;
201 
202     if (profile_name_override) {
203         options.profile_name_override = aws_jni_byte_cursor_from_jbyteArray_acquire(env, profile_name_override);
204     }
205 
206     if (config_file_name_override) {
207         options.config_file_name_override = aws_jni_byte_cursor_from_jbyteArray_acquire(env, config_file_name_override);
208     }
209 
210     if (credentials_file_name_override) {
211         options.credentials_file_name_override =
212             aws_jni_byte_cursor_from_jbyteArray_acquire(env, credentials_file_name_override);
213     }
214 
215     struct aws_credentials_provider *provider = aws_credentials_provider_new_profile(allocator, &options);
216     if (provider == NULL) {
217         s_callback_data_clean_up(env, allocator, callback_data);
218         aws_jni_throw_runtime_exception(env, "Failed to create profile credentials provider");
219     } else {
220         callback_data->provider = provider;
221     }
222 
223     if (profile_name_override) {
224         aws_jni_byte_cursor_from_jbyteArray_release(env, profile_name_override, options.profile_name_override);
225     }
226 
227     if (config_file_name_override) {
228         aws_jni_byte_cursor_from_jbyteArray_release(env, config_file_name_override, options.config_file_name_override);
229     }
230 
231     if (credentials_file_name_override) {
232         aws_jni_byte_cursor_from_jbyteArray_release(
233             env, credentials_file_name_override, options.credentials_file_name_override);
234     }
235 
236     return (jlong)provider;
237 }
238 
239 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_EcsCredentialsProvider_ecsCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrapHandle,jlong tls_context_handle,jbyteArray host,jbyteArray path_and_query,jbyteArray auth_token)240     Java_software_amazon_awssdk_crt_auth_credentials_EcsCredentialsProvider_ecsCredentialsProviderNew(
241         JNIEnv *env,
242         jclass jni_class,
243         jobject java_crt_credentials_provider,
244         jlong bootstrapHandle,
245         jlong tls_context_handle,
246         jbyteArray host,
247         jbyteArray path_and_query,
248         jbyteArray auth_token) {
249 
250     (void)jni_class;
251     (void)env;
252     aws_cache_jni_ids(env);
253 
254     struct aws_allocator *allocator = aws_jni_get_allocator();
255     struct aws_credentials_provider_callback_data *callback_data =
256         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
257     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
258 
259     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
260     AWS_FATAL_ASSERT(jvmresult == 0);
261 
262     struct aws_credentials_provider_ecs_options options;
263     AWS_ZERO_STRUCT(options);
264     options.bootstrap = (struct aws_client_bootstrap *)bootstrapHandle;
265     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
266     options.shutdown_options.shutdown_user_data = callback_data;
267     options.tls_ctx = (struct aws_tls_ctx *)tls_context_handle;
268 
269     if (host) {
270         options.host = aws_jni_byte_cursor_from_jbyteArray_acquire(env, host);
271     }
272 
273     if (path_and_query) {
274         options.path_and_query = aws_jni_byte_cursor_from_jbyteArray_acquire(env, path_and_query);
275     }
276 
277     if (auth_token) {
278         options.auth_token = aws_jni_byte_cursor_from_jbyteArray_acquire(env, auth_token);
279     }
280 
281     struct aws_credentials_provider *provider = aws_credentials_provider_new_ecs(allocator, &options);
282     if (provider == NULL) {
283         s_callback_data_clean_up(env, allocator, callback_data);
284         aws_jni_throw_runtime_exception(env, "Failed to create ECS credentials provider");
285     } else {
286         callback_data->provider = provider;
287     }
288 
289     if (host) {
290         aws_jni_byte_cursor_from_jbyteArray_release(env, host, options.host);
291     }
292 
293     if (path_and_query) {
294         aws_jni_byte_cursor_from_jbyteArray_release(env, path_and_query, options.path_and_query);
295     }
296 
297     if (auth_token) {
298         aws_jni_byte_cursor_from_jbyteArray_release(env, auth_token, options.auth_token);
299     }
300 
301     return (jlong)provider;
302 }
303 
304 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_StsCredentialsProvider_stsCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrapHandle,jlong tls_context_handle,jlong creds_provider,jbyteArray role_arn,jbyteArray session_name,jlong duration_seconds)305     Java_software_amazon_awssdk_crt_auth_credentials_StsCredentialsProvider_stsCredentialsProviderNew(
306         JNIEnv *env,
307         jclass jni_class,
308         jobject java_crt_credentials_provider,
309         jlong bootstrapHandle,
310         jlong tls_context_handle,
311         jlong creds_provider,
312         jbyteArray role_arn,
313         jbyteArray session_name,
314         jlong duration_seconds) {
315 
316     (void)jni_class;
317     (void)env;
318     aws_cache_jni_ids(env);
319 
320     struct aws_allocator *allocator = aws_jni_get_allocator();
321     struct aws_credentials_provider_callback_data *callback_data =
322         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
323     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
324 
325     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
326     AWS_FATAL_ASSERT(jvmresult == 0);
327 
328     struct aws_credentials_provider_sts_options options;
329     AWS_ZERO_STRUCT(options);
330     options.bootstrap = (struct aws_client_bootstrap *)bootstrapHandle;
331     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
332     options.shutdown_options.shutdown_user_data = callback_data;
333     options.tls_ctx = (struct aws_tls_ctx *)tls_context_handle;
334 
335     options.creds_provider = (struct aws_credentials_provider *)creds_provider;
336 
337     if (role_arn) {
338         options.role_arn = aws_jni_byte_cursor_from_jbyteArray_acquire(env, role_arn);
339     }
340 
341     if (session_name) {
342         options.session_name = aws_jni_byte_cursor_from_jbyteArray_acquire(env, session_name);
343     }
344 
345     options.duration_seconds =
346         (uint16_t)aws_timestamp_convert(duration_seconds, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_SECS, NULL);
347 
348     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts(allocator, &options);
349     if (provider == NULL) {
350         s_callback_data_clean_up(env, allocator, callback_data);
351         aws_jni_throw_runtime_exception(env, "Failed to create STS credentials provider");
352     } else {
353         callback_data->provider = provider;
354     }
355 
356     if (role_arn) {
357         aws_jni_byte_cursor_from_jbyteArray_release(env, role_arn, options.role_arn);
358     }
359 
360     if (session_name) {
361         aws_jni_byte_cursor_from_jbyteArray_release(env, session_name, options.session_name);
362     }
363 
364     return (jlong)provider;
365 }
366 
367 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_StsWebIdentityCredentialsProvider_stsWebIdentityCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrapHandle,jlong tls_context_handle)368     Java_software_amazon_awssdk_crt_auth_credentials_StsWebIdentityCredentialsProvider_stsWebIdentityCredentialsProviderNew(
369         JNIEnv *env,
370         jclass jni_class,
371         jobject java_crt_credentials_provider,
372         jlong bootstrapHandle,
373         jlong tls_context_handle) {
374 
375     (void)jni_class;
376     (void)env;
377     aws_cache_jni_ids(env);
378 
379     struct aws_allocator *allocator = aws_jni_get_allocator();
380     struct aws_credentials_provider_callback_data *callback_data =
381         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
382     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
383 
384     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
385     AWS_FATAL_ASSERT(jvmresult == 0);
386 
387     struct aws_credentials_provider_sts_web_identity_options options;
388     AWS_ZERO_STRUCT(options);
389     options.bootstrap = (struct aws_client_bootstrap *)bootstrapHandle;
390     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
391     options.shutdown_options.shutdown_user_data = callback_data;
392     options.tls_ctx = (struct aws_tls_ctx *)tls_context_handle;
393 
394     struct aws_credentials_provider *provider = aws_credentials_provider_new_sts_web_identity(allocator, &options);
395     if (provider == NULL) {
396         s_callback_data_clean_up(env, allocator, callback_data);
397         aws_jni_throw_runtime_exception(env, "Failed to create STS web identity credentials provider");
398     } else {
399         callback_data->provider = provider;
400     }
401 
402     return (jlong)provider;
403 }
404 
405 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_X509CredentialsProvider_x509CredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jlong bootstrap_handle,jlong tls_context_handle,jbyteArray thing_name,jbyteArray role_alias,jbyteArray endpoint,jint proxy_connection_type,jbyteArray jni_proxy_host,jint jni_proxy_port,jlong jni_proxy_tls_context,jint jni_proxy_authorization_type,jbyteArray jni_proxy_authorization_username,jbyteArray jni_proxy_authorization_password)406     Java_software_amazon_awssdk_crt_auth_credentials_X509CredentialsProvider_x509CredentialsProviderNew(
407         JNIEnv *env,
408         jclass jni_class,
409         jobject java_crt_credentials_provider,
410         jlong bootstrap_handle,
411         jlong tls_context_handle,
412         jbyteArray thing_name,
413         jbyteArray role_alias,
414         jbyteArray endpoint,
415         jint proxy_connection_type,
416         jbyteArray jni_proxy_host,
417         jint jni_proxy_port,
418         jlong jni_proxy_tls_context,
419         jint jni_proxy_authorization_type,
420         jbyteArray jni_proxy_authorization_username,
421         jbyteArray jni_proxy_authorization_password) {
422 
423     (void)jni_class;
424     (void)env;
425     aws_cache_jni_ids(env);
426 
427     struct aws_allocator *allocator = aws_jni_get_allocator();
428     struct aws_credentials_provider_callback_data *callback_data =
429         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
430     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
431 
432     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
433     AWS_FATAL_ASSERT(jvmresult == 0);
434 
435     struct aws_tls_connection_options tls_connection_options;
436     AWS_ZERO_STRUCT(tls_connection_options);
437     aws_tls_connection_options_init_from_ctx(&tls_connection_options, (struct aws_tls_ctx *)tls_context_handle);
438 
439     struct aws_credentials_provider_x509_options options;
440     AWS_ZERO_STRUCT(options);
441     options.bootstrap = (struct aws_client_bootstrap *)bootstrap_handle;
442     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
443     options.shutdown_options.shutdown_user_data = callback_data;
444     options.tls_connection_options = &tls_connection_options;
445     options.thing_name = aws_jni_byte_cursor_from_jbyteArray_acquire(env, thing_name);
446     options.role_alias = aws_jni_byte_cursor_from_jbyteArray_acquire(env, role_alias);
447     options.endpoint = aws_jni_byte_cursor_from_jbyteArray_acquire(env, endpoint);
448 
449     struct aws_tls_connection_options proxy_tls_connection_options;
450     AWS_ZERO_STRUCT(proxy_tls_connection_options);
451     struct aws_http_proxy_options proxy_options;
452     AWS_ZERO_STRUCT(proxy_options);
453 
454     aws_http_proxy_options_jni_init(
455         env,
456         &proxy_options,
457         proxy_connection_type,
458         &proxy_tls_connection_options,
459         jni_proxy_host,
460         jni_proxy_port,
461         jni_proxy_authorization_username,
462         jni_proxy_authorization_password,
463         jni_proxy_authorization_type,
464         (struct aws_tls_ctx *)jni_proxy_tls_context);
465 
466     if (jni_proxy_host != NULL) {
467         options.proxy_options = &proxy_options;
468     }
469 
470     struct aws_credentials_provider *provider = aws_credentials_provider_new_x509(allocator, &options);
471     if (provider == NULL) {
472         s_callback_data_clean_up(env, allocator, callback_data);
473         aws_jni_throw_runtime_exception(env, "Failed to create X509 credentials provider");
474     } else {
475         callback_data->provider = provider;
476     }
477 
478     aws_jni_byte_cursor_from_jbyteArray_release(env, thing_name, options.thing_name);
479     aws_jni_byte_cursor_from_jbyteArray_release(env, role_alias, options.role_alias);
480     aws_jni_byte_cursor_from_jbyteArray_release(env, endpoint, options.endpoint);
481 
482     aws_http_proxy_options_jni_clean_up(
483         env, &proxy_options, jni_proxy_host, jni_proxy_authorization_username, jni_proxy_authorization_password);
484 
485     aws_tls_connection_options_clean_up(&tls_connection_options);
486 
487     return (jlong)provider;
488 }
489 
490 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_CachedCredentialsProvider_cachedCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jint cached_duration_in_seconds,jlong native_cached_provider)491     Java_software_amazon_awssdk_crt_auth_credentials_CachedCredentialsProvider_cachedCredentialsProviderNew(
492         JNIEnv *env,
493         jclass jni_class,
494         jobject java_crt_credentials_provider,
495         jint cached_duration_in_seconds,
496         jlong native_cached_provider) {
497 
498     (void)jni_class;
499     aws_cache_jni_ids(env);
500 
501     if (native_cached_provider == 0) {
502         aws_jni_throw_runtime_exception(
503             env, "CachedCredentialsProviderials.cachedCredentialsProviderNew: cached provider is null");
504         return 0;
505     }
506 
507     struct aws_allocator *allocator = aws_jni_get_allocator();
508 
509     struct aws_credentials_provider_callback_data *callback_data =
510         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
511     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
512 
513     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
514     AWS_FATAL_ASSERT(jvmresult == 0);
515 
516     struct aws_credentials_provider_cached_options options;
517     AWS_ZERO_STRUCT(options);
518     options.refresh_time_in_milliseconds =
519         aws_timestamp_convert(cached_duration_in_seconds, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL);
520     options.source = (struct aws_credentials_provider *)native_cached_provider;
521 
522     options.shutdown_options.shutdown_callback = s_on_shutdown_complete;
523     options.shutdown_options.shutdown_user_data = callback_data;
524 
525     struct aws_credentials_provider *provider = aws_credentials_provider_new_cached(allocator, &options);
526     if (provider == NULL) {
527         s_callback_data_clean_up(env, allocator, callback_data);
528         aws_jni_throw_runtime_exception(env, "Failed to create cached credentials provider");
529     } else {
530         callback_data->provider = provider;
531     }
532 
533     return (jlong)provider;
534 }
535 
s_credentials_provider_delegate_get_credentials(void * delegate_user_data,aws_on_get_credentials_callback_fn callback,void * callback_user_data)536 static int s_credentials_provider_delegate_get_credentials(
537     void *delegate_user_data,
538     aws_on_get_credentials_callback_fn callback,
539     void *callback_user_data) {
540 
541     struct aws_credentials_provider_callback_data *callback_data = delegate_user_data;
542 
543     int return_value = AWS_OP_ERR;
544 
545     /********** JNI ENV ACQUIRE **********/
546     JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
547     if (env == NULL) {
548         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
549         return AWS_OP_ERR;
550     }
551 
552     // Fetch credentials from java
553     jobject java_credentials = (*env)->CallObjectMethod(
554         env,
555         callback_data->jni_delegate_credential_handler,
556         credentials_handler_properties.on_handler_get_credentials_method_id);
557     if (aws_jni_check_and_clear_exception(env)) {
558         aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
559         goto done;
560     }
561 
562     struct aws_credentials *native_credentials = aws_credentials_new_from_java_credentials(env, java_credentials);
563     if (!native_credentials) {
564         aws_jni_throw_runtime_exception(env, "Failed to create native credentials");
565         // error has been raised from creating function
566         goto done;
567     }
568     callback(native_credentials, AWS_ERROR_SUCCESS, callback_user_data);
569     aws_credentials_release(native_credentials);
570 
571     return_value = AWS_OP_SUCCESS;
572 
573 done:
574     (*env)->DeleteLocalRef(env, java_credentials);
575 
576     aws_jni_release_thread_env(callback_data->jvm, env);
577     /********** JNI ENV RELEASE **********/
578 
579     return return_value;
580 }
581 
582 JNIEXPORT jlong JNICALL
Java_software_amazon_awssdk_crt_auth_credentials_DelegateCredentialsProvider_delegateCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject java_crt_credentials_provider,jobject jni_delegate_credential_handler)583     Java_software_amazon_awssdk_crt_auth_credentials_DelegateCredentialsProvider_delegateCredentialsProviderNew(
584         JNIEnv *env,
585         jclass jni_class,
586         jobject java_crt_credentials_provider,
587         jobject jni_delegate_credential_handler) {
588 
589     (void)jni_class;
590     (void)env;
591     aws_cache_jni_ids(env);
592 
593     struct aws_allocator *allocator = aws_jni_get_allocator();
594     struct aws_credentials_provider_callback_data *callback_data =
595         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
596     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, java_crt_credentials_provider);
597     callback_data->jni_delegate_credential_handler = (*env)->NewGlobalRef(env, jni_delegate_credential_handler);
598 
599     struct aws_credentials_provider_delegate_options options = {
600         .get_credentials = s_credentials_provider_delegate_get_credentials,
601         .delegate_user_data = callback_data,
602         .shutdown_options =
603             {
604                 .shutdown_callback = s_on_shutdown_complete,
605                 .shutdown_user_data = callback_data,
606             },
607     };
608 
609     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
610     AWS_FATAL_ASSERT(jvmresult == 0);
611 
612     struct aws_credentials_provider *provider = aws_credentials_provider_new_delegate(allocator, &options);
613     if (provider == NULL) {
614         s_callback_data_clean_up(env, allocator, callback_data);
615         aws_jni_throw_runtime_exception(env, "Failed to create delegate credentials provider");
616     } else {
617         callback_data->provider = provider;
618     }
619 
620     return (jlong)provider;
621 }
622 
s_fill_in_logins(struct aws_array_list * logins,struct aws_byte_cursor marshalled_logins)623 static int s_fill_in_logins(struct aws_array_list *logins, struct aws_byte_cursor marshalled_logins) {
624     struct aws_byte_cursor logins_cursor = marshalled_logins;
625     uint32_t field_len = 0;
626 
627     while (logins_cursor.len > 0) {
628         if (!aws_byte_cursor_read_be32(&logins_cursor, &field_len)) {
629             return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
630         }
631 
632         struct aws_byte_cursor identity_provider_name = aws_byte_cursor_advance(&logins_cursor, field_len);
633 
634         if (!aws_byte_cursor_read_be32(&logins_cursor, &field_len)) {
635             return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
636         }
637 
638         struct aws_byte_cursor identity_provider_token = aws_byte_cursor_advance(&logins_cursor, field_len);
639 
640         struct aws_cognito_identity_provider_token_pair login_pair = {
641             .identity_provider_name = identity_provider_name,
642             .identity_provider_token = identity_provider_token,
643         };
644 
645         aws_array_list_push_back(logins, &login_pair);
646     }
647 
648     return AWS_OP_SUCCESS;
649 }
650 
651 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_credentials_CognitoCredentialsProvider_cognitoCredentialsProviderNew(JNIEnv * env,jclass jni_class,jobject crt_credentials_provider,jlong native_bootstrap,jlong native_tls_context,jstring endpoint,jstring identity,jstring custom_role_arn,jbyteArray marshalled_logins,jint proxy_connection_type,jbyteArray proxy_host,jint proxy_port,jlong native_proxy_tls_context,jint proxy_authorization_type,jbyteArray proxy_authorization_username,jbyteArray proxy_authorization_password)652 jlong JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CognitoCredentialsProvider_cognitoCredentialsProviderNew(
653     JNIEnv *env,
654     jclass jni_class,
655     jobject crt_credentials_provider,
656     jlong native_bootstrap,
657     jlong native_tls_context,
658     jstring endpoint,
659     jstring identity,
660     jstring custom_role_arn,
661     jbyteArray marshalled_logins,
662     jint proxy_connection_type,
663     jbyteArray proxy_host,
664     jint proxy_port,
665     jlong native_proxy_tls_context,
666     jint proxy_authorization_type,
667     jbyteArray proxy_authorization_username,
668     jbyteArray proxy_authorization_password) {
669 
670     (void)jni_class;
671     (void)env;
672     aws_cache_jni_ids(env);
673 
674     struct aws_allocator *allocator = aws_jni_get_allocator();
675     struct aws_credentials_provider *provider = NULL;
676     struct aws_credentials_provider_callback_data *callback_data = NULL;
677 
678     struct aws_tls_connection_options proxy_tls_connection_options;
679     AWS_ZERO_STRUCT(proxy_tls_connection_options);
680     struct aws_http_proxy_options proxy_options;
681     AWS_ZERO_STRUCT(proxy_options);
682 
683     struct aws_byte_cursor endpoint_cursor;
684     AWS_ZERO_STRUCT(endpoint_cursor);
685     struct aws_byte_cursor identity_cursor;
686     AWS_ZERO_STRUCT(identity_cursor);
687     struct aws_byte_cursor custom_role_arn_cursor;
688     AWS_ZERO_STRUCT(custom_role_arn_cursor);
689     struct aws_byte_cursor logins_cursor;
690     AWS_ZERO_STRUCT(logins_cursor);
691 
692     struct aws_array_list logins;
693     aws_array_list_init_dynamic(&logins, allocator, 0, sizeof(struct aws_cognito_identity_provider_token_pair));
694 
695     if (endpoint == NULL || identity == NULL) {
696         goto done;
697     }
698 
699     endpoint_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, endpoint);
700     identity_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, identity);
701 
702     callback_data = aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_callback_data));
703 
704     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
705     AWS_FATAL_ASSERT(jvmresult == 0);
706     callback_data->java_crt_credentials_provider = (*env)->NewWeakGlobalRef(env, crt_credentials_provider);
707 
708     struct aws_credentials_provider_cognito_options options = {
709         .shutdown_options =
710             {
711                 .shutdown_callback = s_on_shutdown_complete,
712                 .shutdown_user_data = callback_data,
713             },
714         .endpoint = endpoint_cursor,
715         .identity = identity_cursor,
716         .bootstrap = (void *)native_bootstrap,
717         .tls_ctx = (void *)native_tls_context,
718     };
719 
720     if (custom_role_arn != NULL) {
721         custom_role_arn_cursor = aws_jni_byte_cursor_from_jstring_acquire(env, custom_role_arn);
722         options.custom_role_arn = &custom_role_arn_cursor;
723     }
724 
725     if (marshalled_logins != NULL) {
726         logins_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, marshalled_logins);
727         if (s_fill_in_logins(&logins, logins_cursor)) {
728             goto done;
729         }
730 
731         options.logins = logins.data;
732         options.login_count = aws_array_list_length(&logins);
733     }
734 
735     if (proxy_host != NULL) {
736         aws_http_proxy_options_jni_init(
737             env,
738             &proxy_options,
739             proxy_connection_type,
740             &proxy_tls_connection_options,
741             proxy_host,
742             proxy_port,
743             proxy_authorization_username,
744             proxy_authorization_password,
745             proxy_authorization_type,
746             (struct aws_tls_ctx *)native_proxy_tls_context);
747 
748         options.http_proxy_options = &proxy_options;
749     }
750 
751     provider = aws_credentials_provider_new_cognito(allocator, &options);
752     if (provider != NULL) {
753         callback_data->provider = provider;
754     }
755 
756 done:
757 
758     aws_jni_byte_cursor_from_jstring_release(env, endpoint, endpoint_cursor);
759     aws_jni_byte_cursor_from_jstring_release(env, identity, identity_cursor);
760     aws_jni_byte_cursor_from_jstring_release(env, custom_role_arn, custom_role_arn_cursor);
761     aws_jni_byte_cursor_from_jbyteArray_release(env, marshalled_logins, logins_cursor);
762 
763     aws_http_proxy_options_jni_clean_up(
764         env, &proxy_options, proxy_host, proxy_authorization_username, proxy_authorization_password);
765 
766     aws_array_list_clean_up(&logins);
767 
768     if (provider == NULL) {
769         s_callback_data_clean_up(env, allocator, callback_data);
770         aws_jni_throw_runtime_exception(env, "Failed to create native cognito credentials provider");
771     }
772 
773     return (jlong)provider;
774 }
775 
776 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_credentials_CredentialsProvider_credentialsProviderDestroy(JNIEnv * env,jclass jni_cp,jobject cp_object,jlong cp_addr)777 void JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CredentialsProvider_credentialsProviderDestroy(
778     JNIEnv *env,
779     jclass jni_cp,
780     jobject cp_object,
781     jlong cp_addr) {
782     (void)jni_cp;
783     (void)cp_object;
784     aws_cache_jni_ids(env);
785 
786     struct aws_credentials_provider *provider = (struct aws_credentials_provider *)cp_addr;
787     if (!provider) {
788         aws_jni_throw_runtime_exception(
789             env, "CredentialsProvider.credentialsProviderDestroy: instance should be non-null at destruction time");
790         return;
791     }
792 
793     aws_credentials_provider_release(provider);
794 }
795 
796 struct aws_credentials_provider_get_credentials_callback_data {
797     JavaVM *jvm;
798     struct aws_credentials_provider *provider;
799     jobject java_crt_credentials_provider;
800     jobject java_credentials_future;
801 };
802 
s_cp_callback_data_clean_up(struct aws_credentials_provider_get_credentials_callback_data * callback_data,JNIEnv * env)803 static void s_cp_callback_data_clean_up(
804     struct aws_credentials_provider_get_credentials_callback_data *callback_data,
805     JNIEnv *env) {
806     if (callback_data == NULL || env == NULL) {
807         return;
808     }
809 
810     (*env)->DeleteGlobalRef(env, callback_data->java_crt_credentials_provider);
811     (*env)->DeleteGlobalRef(env, callback_data->java_credentials_future);
812 
813     aws_credentials_provider_release(callback_data->provider);
814 
815     // We're done with this callback data, free it.
816     aws_mem_release(aws_jni_get_allocator(), callback_data);
817 }
818 
s_on_get_credentials_callback(struct aws_credentials * credentials,int error_code,void * user_data)819 static void s_on_get_credentials_callback(struct aws_credentials *credentials, int error_code, void *user_data) {
820     (void)error_code;
821 
822     struct aws_credentials_provider_get_credentials_callback_data *callback_data = user_data;
823 
824     /********** JNI ENV ACQUIRE **********/
825     JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
826     if (env == NULL) {
827         /* If we can't get an environment, then the JVM is probably shutting down.  Don't crash. */
828         return;
829     }
830 
831     jobject java_credentials = NULL;
832 
833     if (credentials) {
834         java_credentials = aws_java_credentials_from_native_new(env, credentials);
835     }
836 
837     (*env)->CallVoidMethod(
838         env,
839         callback_data->java_crt_credentials_provider,
840         credentials_provider_properties.on_get_credentials_complete_method_id,
841         callback_data->java_credentials_future,
842         java_credentials);
843 
844     AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
845 
846     if (java_credentials != NULL) {
847         (*env)->DeleteLocalRef(env, java_credentials);
848     }
849 
850     JavaVM *jvm = callback_data->jvm;
851     s_cp_callback_data_clean_up(callback_data, env);
852 
853     aws_jni_release_thread_env(jvm, env);
854     /********** JNI ENV RELEASE **********/
855 }
856 
857 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_credentials_CredentialsProvider_credentialsProviderGetCredentials(JNIEnv * env,jclass jni_cp,jobject java_crt_credentials_provider,jobject java_credentials_future,jlong native_credentials_provider)858 void JNICALL Java_software_amazon_awssdk_crt_auth_credentials_CredentialsProvider_credentialsProviderGetCredentials(
859     JNIEnv *env,
860     jclass jni_cp,
861     jobject java_crt_credentials_provider,
862     jobject java_credentials_future,
863     jlong native_credentials_provider) {
864     (void)jni_cp;
865     aws_cache_jni_ids(env);
866 
867     struct aws_credentials_provider *provider = (struct aws_credentials_provider *)native_credentials_provider;
868     if (!provider) {
869         aws_jni_throw_runtime_exception(
870             env, "CredentialsProvider.credentialsProviderGetCredentials: instance should be non-null");
871         return;
872     }
873 
874     if (java_crt_credentials_provider == NULL || java_credentials_future == NULL) {
875         aws_jni_throw_runtime_exception(
876             env, "CredentialsProvider.credentialsProviderGetCredentials: called with null parameters");
877         return;
878     }
879 
880     struct aws_allocator *allocator = aws_jni_get_allocator();
881     struct aws_credentials_provider_get_credentials_callback_data *callback_data =
882         aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials_provider_get_credentials_callback_data));
883     callback_data->java_crt_credentials_provider = (*env)->NewGlobalRef(env, java_crt_credentials_provider);
884     callback_data->java_credentials_future = (*env)->NewGlobalRef(env, java_credentials_future);
885     callback_data->provider = provider;
886 
887     jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
888     AWS_FATAL_ASSERT(jvmresult == 0);
889 
890     aws_credentials_provider_acquire(provider);
891 
892     if (aws_credentials_provider_get_credentials(provider, s_on_get_credentials_callback, callback_data)) {
893         aws_jni_throw_runtime_exception(env, "CrtCredentialsProvider.credentialsProviderGetCredentials: call failure");
894         /* callback will not be invoked on failure, clean up the resource here. */
895         s_cp_callback_data_clean_up(callback_data, env);
896     }
897 }
898 
899 #if UINTPTR_MAX == 0xffffffff
900 #    if defined(_MSC_VER)
901 #        pragma warning(pop)
902 #    else
903 #        pragma GCC diagnostic pop
904 #    endif
905 #endif
906