in source/io.c [219:442]
napi_value aws_napi_io_tls_ctx_new(napi_env env, napi_callback_info info) {
struct aws_allocator *alloc = aws_napi_get_allocator();
napi_status status = napi_ok;
(void)status;
napi_value node_args[12];
size_t num_args = AWS_ARRAY_SIZE(node_args);
napi_value *arg = &node_args[0];
if (napi_ok != napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL)) {
napi_throw_error(env, NULL, "Failed to retreive callback information");
return NULL;
}
if (num_args != AWS_ARRAY_SIZE(node_args)) {
napi_throw_error(env, NULL, "aws_nodejs_io_client_tls_ctx_new needs exactly 12 arguments");
return NULL;
}
napi_value result = NULL;
#ifdef __APPLE__
struct aws_byte_buf pkcs12_path;
AWS_ZERO_STRUCT(pkcs12_path);
struct aws_byte_buf pkcs12_pwd;
AWS_ZERO_STRUCT(pkcs12_pwd);
#endif
struct aws_tls_ctx_options ctx_options;
AWS_ZERO_STRUCT(ctx_options);
struct aws_string *ca_path = NULL;
struct aws_string *ca_file = NULL;
struct aws_byte_buf certificate;
AWS_ZERO_STRUCT(certificate);
struct aws_byte_buf private_key;
AWS_ZERO_STRUCT(private_key);
struct aws_byte_buf ca_buf;
AWS_ZERO_STRUCT(ca_buf);
struct aws_string *cert_path = NULL;
struct aws_string *pkey_path = NULL;
struct aws_string *alpn_list = NULL;
uint32_t min_tls_version = AWS_IO_TLS_VER_SYS_DEFAULTS;
napi_value node_tls_version = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_tls_version)) {
napi_value node_number;
if (napi_ok != napi_coerce_to_number(env, node_tls_version, &node_number)) {
napi_throw_type_error(env, NULL, "min_tls_version must be an enum/Number (or convertible to a Number)");
return result;
}
status = napi_get_value_uint32(env, node_number, &min_tls_version);
AWS_FATAL_ASSERT(status == napi_ok); /* We coerced the value to a number, so this must return ok */
}
napi_value node_ca_file = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_ca_file)) {
ca_file = aws_string_new_from_napi(env, node_ca_file);
if (!ca_file) {
napi_throw_type_error(env, NULL, "ca_filepath must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_ca_path = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_ca_path)) {
ca_path = aws_string_new_from_napi(env, node_ca_path);
if (!ca_path) {
napi_throw_type_error(env, NULL, "ca_dirpath must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_ca_buf = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_ca_buf)) {
if (aws_byte_buf_init_from_napi(&ca_buf, env, node_ca_buf)) {
napi_throw_type_error(env, NULL, "certificate_authority must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_alpn = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_alpn)) {
alpn_list = aws_string_new_from_napi(env, node_alpn);
if (!alpn_list) {
napi_throw_type_error(env, NULL, "alpn_list must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_cert_path = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_cert_path)) {
cert_path = aws_string_new_from_napi(env, node_cert_path);
if (!cert_path) {
napi_throw_type_error(env, NULL, "cert_path must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_cert_buf = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_cert_buf)) {
if (aws_byte_buf_init_from_napi(&certificate, env, node_cert_buf)) {
napi_throw_type_error(env, NULL, "certificate must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_key_path = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_key_path)) {
pkey_path = aws_string_new_from_napi(env, node_key_path);
if (!pkey_path) {
napi_throw_type_error(env, NULL, "private_key_path must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_key_buf = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_key_buf)) {
if (aws_byte_buf_init_from_napi(&private_key, env, node_key_buf)) {
napi_throw_type_error(env, NULL, "private_key must be a String (or convertible to a String)");
goto cleanup;
}
}
napi_value node_pkcs12_path = *arg++;
napi_value node_pkcs12_password = *arg++;
(void)node_pkcs12_path;
(void)node_pkcs12_password;
#ifdef __APPLE__
if (!aws_napi_is_null_or_undefined(env, node_pkcs12_path)) {
if (napi_ok != aws_byte_buf_init_from_napi(&pkcs12_path, env, node_pkcs12_path)) {
napi_throw_type_error(env, NULL, "pkcs12_path must be a String (or convertible to a String)");
goto cleanup;
}
}
if (!aws_napi_is_null_or_undefined(env, node_pkcs12_password)) {
if (napi_ok != aws_byte_buf_init_from_napi(&pkcs12_pwd, env, node_pkcs12_password)) {
napi_throw_type_error(env, NULL, "pkcs12_password must be a String (or convertible to a String)");
goto cleanup;
}
}
#endif /* __APPLE__ */
bool verify_peer = true;
napi_value node_verify_peer = *arg++;
if (!aws_napi_is_null_or_undefined(env, node_verify_peer)) {
napi_value node_bool;
if (napi_ok != napi_coerce_to_bool(env, node_verify_peer, &node_bool)) {
napi_throw_type_error(env, NULL, "verify_peer must be a boolean (or convertible to a boolean)");
goto cleanup;
}
status = napi_get_value_bool(env, node_bool, &verify_peer);
AWS_FATAL_ASSERT(status == napi_ok);
}
if (certificate.buffer && private_key.buffer) {
struct aws_byte_cursor cert_cursor = aws_byte_cursor_from_buf(&certificate);
struct aws_byte_cursor pkey_cursor = aws_byte_cursor_from_buf(&private_key);
if (aws_tls_ctx_options_init_client_mtls(&ctx_options, alloc, &cert_cursor, &pkey_cursor)) {
aws_napi_throw_last_error(env);
goto cleanup;
}
} else if (cert_path && pkey_path) {
if (aws_tls_ctx_options_init_client_mtls_from_path(
&ctx_options, alloc, aws_string_c_str(cert_path), aws_string_c_str(pkey_path))) {
aws_napi_throw_last_error(env);
goto cleanup;
}
} else {
aws_tls_ctx_options_init_default_client(&ctx_options, alloc);
}
if (ca_buf.buffer) {
struct aws_byte_cursor ca_cursor = aws_byte_cursor_from_buf(&ca_buf);
if (aws_tls_ctx_options_override_default_trust_store(&ctx_options, &ca_cursor)) {
aws_napi_throw_last_error(env);
goto cleanup;
}
} else if (ca_path || ca_file) {
if (aws_tls_ctx_options_override_default_trust_store_from_path(
&ctx_options, ca_path ? aws_string_c_str(ca_path) : NULL, ca_file ? aws_string_c_str(ca_file) : NULL)) {
aws_napi_throw_last_error(env);
goto cleanup;
}
}
if (alpn_list) {
aws_tls_ctx_options_set_alpn_list(&ctx_options, aws_string_c_str(alpn_list));
}
aws_tls_ctx_options_set_verify_peer(&ctx_options, verify_peer);
struct aws_tls_ctx *tls_ctx = aws_tls_client_ctx_new(alloc, &ctx_options);
if (!tls_ctx) {
napi_throw_error(env, NULL, "Unable to create TLS context");
goto cleanup;
}
napi_value node_external;
if (napi_ok != napi_create_external(env, tls_ctx, s_tls_ctx_finalize, NULL, &node_external)) {
napi_throw_error(env, NULL, "Failed create n-api external");
goto cleanup;
}
result = node_external;
cleanup:
#ifdef __APPLE__
aws_byte_buf_clean_up_secure(&pkcs12_path);
aws_byte_buf_clean_up_secure(&pkcs12_pwd);
#endif
aws_string_destroy_secure(cert_path);
aws_byte_buf_clean_up_secure(&certificate);
aws_string_destroy_secure(pkey_path);
aws_byte_buf_clean_up_secure(&private_key);
aws_byte_buf_clean_up_secure(&ca_buf);
aws_string_destroy(alpn_list);
aws_tls_ctx_options_clean_up(&ctx_options);
return result;
}