Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
jmklix authored Feb 6, 2024
2 parents 395c324 + 4c65ce5 commit 6eabc5b
Show file tree
Hide file tree
Showing 32 changed files with 1,465 additions and 870 deletions.
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Declare files that will always have CRLF line endings on checkout.
tests/resources/testparse_crlf.crt text eol=crlf
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# IDE Artifacts
.metadata
.build
.vscode
.idea
*.d
Debug
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ Sockets interact directly with the underlying io and are invoked directly by the

Platform | Implementation
--- | ---
Linux | Signal-to-noise (s2n) see github.com/awslabs/s2n
Linux | Signal-to-noise (s2n) see: https://github.com/aws/s2n-tls
BSD Variants | s2n
Apple Devices | Security Framework/ Secure Transport. See https://developer.apple.com/documentation/security/secure_transport
Windows | Secure Channel. See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380123(v=vs.85).aspx
Expand Down
4 changes: 2 additions & 2 deletions include/aws/io/channel_bootstrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ struct aws_server_bootstrap {
struct aws_socket_channel_bootstrap_options {
struct aws_client_bootstrap *bootstrap;
const char *host_name;
uint16_t port;
uint32_t port;
const struct aws_socket_options *socket_options;
const struct aws_tls_connection_options *tls_options;
aws_client_bootstrap_on_channel_event_fn *creation_callback;
Expand Down Expand Up @@ -208,7 +208,7 @@ struct aws_socket_channel_bootstrap_options {
struct aws_server_socket_channel_bootstrap_options {
struct aws_server_bootstrap *bootstrap;
const char *host_name;
uint16_t port;
uint32_t port;
const struct aws_socket_options *socket_options;
const struct aws_tls_connection_options *tls_options;
aws_server_bootstrap_on_accept_channel_setup_fn *incoming_callback;
Expand Down
2 changes: 2 additions & 0 deletions include/aws/io/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ enum aws_io_errors {

AWS_IO_TLS_ERROR_READ_FAILURE,

AWS_ERROR_PEM_MALFORMED,

AWS_IO_ERROR_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_IO_PACKAGE_ID),
AWS_IO_INVALID_FILE_HANDLE = AWS_ERROR_INVALID_FILE_HANDLE,
};
Expand Down
1 change: 1 addition & 0 deletions include/aws/io/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum aws_io_log_subject {
AWS_LS_IO_EXPONENTIAL_BACKOFF_RETRY_STRATEGY,
AWS_LS_IO_STANDARD_RETRY_STRATEGY,
AWS_LS_IO_PKCS11,
AWS_LS_IO_PEM,
AWS_IO_LS_LAST = AWS_LOG_SUBJECT_END_RANGE(AWS_C_IO_PACKAGE_ID)
};
AWS_POP_SANE_WARNING_LEVEL
Expand Down
99 changes: 99 additions & 0 deletions include/aws/io/pem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef AWS_IO_PEM_H
#define AWS_IO_PEM_H

/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/io/io.h>

AWS_EXTERN_C_BEGIN

/*
* Naming follows OpenSSL convention for PEM types.
* Refer to comment after each enum value for the type string it represents.
*/
enum aws_pem_object_type {
AWS_PEM_TYPE_UNKNOWN = 0,
AWS_PEM_TYPE_X509_OLD, /* X509 CERTIFICATE */
AWS_PEM_TYPE_X509, /* CERTIFICATE */
AWS_PEM_TYPE_X509_TRUSTED, /* TRUSTED CERTIFICATE */
AWS_PEM_TYPE_X509_REQ_OLD, /* NEW CERTIFICATE REQUEST */
AWS_PEM_TYPE_X509_REQ, /* CERTIFICATE REQUEST */
AWS_PEM_TYPE_X509_CRL, /* X509 CRL */
AWS_PEM_TYPE_EVP_PKEY, /* ANY PRIVATE KEY */
AWS_PEM_TYPE_PUBLIC_PKCS8, /* PUBLIC KEY */
AWS_PEM_TYPE_PRIVATE_RSA_PKCS1, /* RSA PRIVATE KEY */
AWS_PEM_TYPE_PUBLIC_RSA_PKCS1, /* RSA PUBLIC KEY */
AWS_PEM_TYPE_PRIVATE_DSA_PKCS1, /* RSA PRIVATE KEY */
AWS_PEM_TYPE_PUBLIC_DSA_PKCS1, /* RSA PUBLIC KEY */
AWS_PEM_TYPE_PKCS7, /* PKCS7 */
AWS_PEM_TYPE_PKCS7_SIGNED_DATA, /* PKCS #7 SIGNED DATA */
AWS_PEM_TYPE_PRIVATE_PKCS8_ENCRYPTED, /* ENCRYPTED PRIVATE KEY */
AWS_PEM_TYPE_PRIVATE_PKCS8, /* PRIVATE KEY */
AWS_PEM_TYPE_DH_PARAMETERS, /* X9.42 DH PARAMETERS */
AWS_PEM_TYPE_DH_PARAMETERS_X942, /* X9.42 DH PARAMETERS */
AWS_PEM_TYPE_SSL_SESSION_PARAMETERS, /* SSL SESSION PARAMETERS */
AWS_PEM_TYPE_DSA_PARAMETERS, /* DSA PARAMETERS */
AWS_PEM_TYPE_ECDSA_PUBLIC, /* ECDSA PUBLIC KEY */
AWS_PEM_TYPE_EC_PARAMETERS, /* EC PARAMETERS */
AWS_PEM_TYPE_EC_PRIVATE, /* EC PRIVATE KEY */
AWS_PEM_TYPE_PARAMETERS, /* PARAMETERS */
AWS_PEM_TYPE_CMS, /* CMS */
AWS_PEM_TYPE_SM2_PARAMETERS /* SM2 PARAMETERS */
};

/*
* Describes PEM object decoded from file.
* data points to raw data bytes of object (decoding will do additional base 64
* decoding for each object).
* type will be set to object type or to AWS_PEM_TYPE_UNKNOWN if it could not
* figure out type.
* type_string is the string between -----BEGIN and -----
*/
struct aws_pem_object {
enum aws_pem_object_type type;
struct aws_string *type_string;
struct aws_byte_buf data;
};

/**
* Cleans up elements of pem_objects list 'aws_pem_objects_init_from_file_contents()'
* and 'aws_pem_objects_init_from_file_path()'.
*/
AWS_IO_API void aws_pem_objects_clean_up(struct aws_array_list *pem_objects);

/**
* Decodes PEM data and reads objects sequentially adding them to pem_objects.
* If it comes across an object it cannot read, list of all object read until
* that point is returned.
* If no objects can be read from PEM or objects could not be base 64 decoded,
* AWS_ERROR_PEM_MALFORMED is raised.
* out_pem_objects stores aws_pem_object struct by value.
* Function will initialize pem_objects list.
* This code is slow, and it allocates, so please try
* not to call this in the middle of something that needs to be fast or resource sensitive.
*/
AWS_IO_API int aws_pem_objects_init_from_file_contents(
struct aws_array_list *pem_objects,
struct aws_allocator *alloc,
struct aws_byte_cursor pem_cursor);

/**
* Decodes PEM data from file and reads objects sequentially adding them to pem_objects.
* If it comes across an object it cannot read, list of all object read until
* that point is returned.
* If no objects can be read from PEM or objects could not be base 64 decoded,
* AWS_ERROR_PEM_MALFORMED is raised.
* out_pem_objects stores aws_pem_object struct by value.
* Function will initialize pem_objects list.
* This code is slow, and it allocates, so please try
* not to call this in the middle of something that needs to be fast or resource sensitive.
*/
AWS_IO_API int aws_pem_objects_init_from_file_path(
struct aws_array_list *pem_objects,
struct aws_allocator *allocator,
const char *filename);

AWS_EXTERN_C_END
#endif /* AWS_IO_PEM_H */
30 changes: 0 additions & 30 deletions include/aws/io/private/pki_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,13 @@ struct aws_string;

AWS_EXTERN_C_BEGIN

/**
* Cleans up and securely zeroes out the outputs of 'aws_decode_pem_to_buffer_list()'
* and 'aws_read_and_decode_pem_file_to_buffer_list()'
*/
AWS_IO_API void aws_cert_chain_clean_up(struct aws_array_list *cert_chain);

/**
* Decodes a PEM file and adds the results to 'cert_chain_or_key' if successful.
* Otherwise, 'cert_chain_or_key' will be empty. The type stored in 'cert_chain_or_key'
* is 'struct aws_byte_buf' by value. This code is slow, and it allocates, so please try
* not to call this in the middle of something that needs to be fast or resource sensitive.
*/
AWS_IO_API int aws_decode_pem_to_buffer_list(
struct aws_allocator *alloc,
const struct aws_byte_cursor *pem_cursor,
struct aws_array_list *cert_chain_or_key);

/**
* Returns the path to the directory and file, respectively, which holds the
* SSL certificate trust store on the system.
*/
AWS_IO_API const char *aws_determine_default_pki_dir(void);
AWS_IO_API const char *aws_determine_default_pki_ca_file(void);

/**
* Decodes a PEM file at 'filename' and adds the results to 'cert_chain_or_key' if successful.
* Otherwise, 'cert_chain_or_key' will be empty.
* The passed-in parameter 'cert_chain_or_key' should be empty and dynamically initialized array_list
* with item type 'struct aws_byte_buf' in value.
* This code is slow, and it allocates, so please try not to call this in the middle of
* something that needs to be fast or resource sensitive.
*/
AWS_IO_API int aws_read_and_decode_pem_file_to_buffer_list(
struct aws_allocator *alloc,
const char *filename,
struct aws_array_list *cert_chain_or_key);

#ifdef AWS_OS_APPLE
# if !defined(AWS_OS_IOS)
/**
Expand Down
2 changes: 1 addition & 1 deletion include/aws/io/retry_strategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ struct aws_exponential_backoff_retry_options {
struct aws_event_loop_group *el_group;
/** Max retries to allow. The default value is 10 */
size_t max_retries;
/** Scaling factor to add for the backoff. Default is 25ms */
/** Scaling factor to add for the backoff. Default is 500ms */
uint32_t backoff_scale_factor_ms;
/** Max retry backoff in seconds. Default is 20 seconds */
uint32_t max_backoff_secs;
Expand Down
18 changes: 17 additions & 1 deletion include/aws/io/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ typedef void(aws_socket_on_readable_fn)(struct aws_socket *socket, int error_cod
#endif
struct aws_socket_endpoint {
char address[AWS_ADDRESS_MAX_LEN];
uint16_t port;
uint32_t port;
};

struct aws_socket {
Expand Down Expand Up @@ -302,6 +302,22 @@ AWS_IO_API int aws_socket_get_error(struct aws_socket *socket);
*/
AWS_IO_API bool aws_socket_is_open(struct aws_socket *socket);

/**
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if connecting to this port is illegal.
* For example, port must be in range 1-65535 to connect with IPv4.
* These port values would fail eventually in aws_socket_connect(),
* but you can use this function to validate earlier.
*/
AWS_IO_API int aws_socket_validate_port_for_connect(uint32_t port, enum aws_socket_domain domain);

/**
* Raises AWS_IO_SOCKET_INVALID_ADDRESS and logs an error if binding to this port is illegal.
* For example, port must in range 0-65535 to bind with IPv4.
* These port values would fail eventually in aws_socket_bind(),
* but you can use this function to validate earlier.
*/
AWS_IO_API int aws_socket_validate_port_for_bind(uint32_t port, enum aws_socket_domain domain);

/**
* Assigns a random address (UUID) for use with AWS_SOCKET_LOCAL (Unix Domain Sockets).
* For use in internal tests only.
Expand Down
87 changes: 80 additions & 7 deletions source/channel_bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ struct client_connection_args {
aws_client_bootstrap_on_channel_event_fn *shutdown_callback;
struct client_channel_data channel_data;
struct aws_socket_options outgoing_options;
uint16_t outgoing_port;
uint32_t outgoing_port;
struct aws_string *host_name;
void *user_data;
uint8_t addresses_count;
Expand Down Expand Up @@ -182,10 +182,14 @@ static struct aws_event_loop *s_get_connection_event_loop(struct client_connecti
return aws_event_loop_group_get_next_loop(args->bootstrap->event_loop_group);
}

static void s_connection_args_setup_callback(
static void s_connect_args_setup_callback_safe(
struct client_connection_args *args,
int error_code,
struct aws_channel *channel) {

AWS_FATAL_ASSERT(
(args->requested_event_loop == NULL) || aws_event_loop_thread_is_callers_thread(args->requested_event_loop));

/* setup_callback is always called exactly once */
AWS_FATAL_ASSERT(!args->setup_called);

Expand All @@ -200,6 +204,75 @@ static void s_connection_args_setup_callback(
s_client_connection_args_release(args);
}

struct aws_connection_args_setup_callback_task {
struct aws_allocator *allocator;
struct aws_task task;
struct client_connection_args *args;
int error_code;
struct aws_channel *channel;
};

static void s_aws_connection_args_setup_callback_task_delete(struct aws_connection_args_setup_callback_task *task) {
if (task == NULL) {
return;
}

s_client_connection_args_release(task->args);
if (task->channel) {
aws_channel_release_hold(task->channel);
}

aws_mem_release(task->allocator, task);
}

void s_aws_connection_args_setup_callback_task_fn(struct aws_task *task, void *arg, enum aws_task_status status) {
(void)task;

struct aws_connection_args_setup_callback_task *callback_task = arg;

if (status == AWS_TASK_STATUS_RUN_READY) {
s_connect_args_setup_callback_safe(callback_task->args, callback_task->error_code, callback_task->channel);
}

s_aws_connection_args_setup_callback_task_delete(callback_task);
}

static struct aws_connection_args_setup_callback_task *s_aws_connection_args_setup_callback_task_new(
struct aws_allocator *allocator,
struct client_connection_args *args,
int error_code,
struct aws_channel *channel) {

struct aws_connection_args_setup_callback_task *task =
aws_mem_calloc(allocator, 1, sizeof(struct aws_connection_args_setup_callback_task));
task->allocator = allocator;
task->args = s_client_connection_args_acquire(args);
task->error_code = error_code;
task->channel = channel;
if (channel != NULL) {
aws_channel_acquire_hold(channel);
}

aws_task_init(
&task->task, s_aws_connection_args_setup_callback_task_fn, task, "safe connection args setup callback");

return task;
}

static void s_connection_args_setup_callback(
struct client_connection_args *args,
int error_code,
struct aws_channel *channel) {

if (args->requested_event_loop == NULL || aws_event_loop_thread_is_callers_thread(args->requested_event_loop)) {
s_connect_args_setup_callback_safe(args, error_code, channel);
} else {
struct aws_connection_args_setup_callback_task *callback_task =
s_aws_connection_args_setup_callback_task_new(args->bootstrap->allocator, args, error_code, channel);
aws_event_loop_schedule_task_now(args->requested_event_loop, &callback_task->task);
}
}

static void s_connection_args_creation_callback(struct client_connection_args *args, struct aws_channel *channel) {

AWS_FATAL_ASSERT(channel != NULL);
Expand Down Expand Up @@ -764,14 +837,14 @@ int aws_client_bootstrap_new_socket_channel(struct aws_socket_channel_bootstrap_
}

const char *host_name = options->host_name;
uint16_t port = options->port;
uint32_t port = options->port;

AWS_LOGF_TRACE(
AWS_LS_IO_CHANNEL_BOOTSTRAP,
"id=%p: attempting to initialize a new client channel to %s:%d",
"id=%p: attempting to initialize a new client channel to %s:%u",
(void *)bootstrap,
host_name,
(int)port);
port);

aws_ref_count_init(
&client_connection_args->ref_count,
Expand Down Expand Up @@ -1363,10 +1436,10 @@ struct aws_socket *aws_server_bootstrap_new_socket_listener(
AWS_LOGF_INFO(
AWS_LS_IO_CHANNEL_BOOTSTRAP,
"id=%p: attempting to initialize a new "
"server socket listener for %s:%d",
"server socket listener for %s:%u",
(void *)bootstrap_options->bootstrap,
bootstrap_options->host_name,
(int)bootstrap_options->port);
bootstrap_options->port);

aws_ref_count_init(
&server_connection_args->ref_count,
Expand Down
Loading

0 comments on commit 6eabc5b

Please sign in to comment.