From 79687bd48f032c5a8db500e8afaedae8af7bd8de Mon Sep 17 00:00:00 2001 From: Francesco Date: Thu, 8 May 2025 18:31:06 +0200 Subject: [PATCH] initial ssl support --- README.md | 1 + include/server/server.h | 13 ++++---- include/utils/utils.h | 4 +++ meson.build | 4 ++- src/main.c | 4 +-- src/server/server.c | 66 +++++++++++++++++++++++++++-------------- src/utils/utils.c | 19 ++++++++++++ 7 files changed, 79 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 3ea058c..9fc7d4b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ A minimal web server. This is a personal project; it is not intended to be a pro ## Requirements - [meson](https://mesonbuild.com/index.html) +- libssl - libcyaml - libyaml - [doxygen](https://www.doxygen.nl/) diff --git a/include/server/server.h b/include/server/server.h index 344c4e2..bc4fd3d 100644 --- a/include/server/server.h +++ b/include/server/server.h @@ -2,6 +2,8 @@ #define CWS_SERVER_H #include +#include +#include #include #include "utils/config.h" @@ -77,13 +79,6 @@ void cws_fd_set_nonblocking(int sockfd); */ int cws_server_accept_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t *theirsa_size); -/** - * @brief Closes all the file descriptors opened - * - * @param[in] hashmap Clients hash map - */ -void cws_server_close_all_fds(cws_hashmap *hashmap); - /** * @brief Disconnect a client * @@ -93,4 +88,8 @@ void cws_server_close_all_fds(cws_hashmap *hashmap); */ void cws_server_close_client(int epfd, int client_fd, cws_hashmap *hashmap); +/* Undocumented functions */ +SSL_CTX *cws_ssl_create_context(); +bool cws_ssl_configure(SSL_CTX *context, cws_config *config); + #endif diff --git a/include/utils/utils.h b/include/utils/utils.h index e6bfa07..1481519 100644 --- a/include/utils/utils.h +++ b/include/utils/utils.h @@ -37,4 +37,8 @@ int my_str_hash_fn(void *key); bool my_str_equal_fn(void *a, void *b); void my_str_free_fn(void *value); +int my_int_hash_fn(void *key); +bool my_int_equal_fn(void *a, void *b); +void my_int_free_fn(void *value); + #endif diff --git a/meson.build b/meson.build index 8421d1c..2a4db60 100644 --- a/meson.build +++ b/meson.build @@ -4,12 +4,14 @@ subdir('src') incdir = include_directories('include') +libssl = dependency('libssl') libyaml = dependency('yaml-0.1') libcyaml = dependency('libcyaml') +deps = [libssl, libyaml, libcyaml] add_global_arguments('-DUSE_COLORS', language : 'c') add_global_arguments('-DEVELOPER', language : 'c') -executable('cws', server, include_directories : incdir, dependencies : [libyaml, libcyaml]) +executable('cws', server, include_directories : incdir, dependencies : deps) executable('testbuild', test, include_directories : incdir) diff --git a/src/main.c b/src/main.c index dc62933..7409dd5 100644 --- a/src/main.c +++ b/src/main.c @@ -14,8 +14,8 @@ int main(int argc, char **argv) { struct sigaction act = {.sa_handler = cws_signal_handler}; ret = sigaction(SIGINT, &act, NULL); - if (!ret) { - CWS_LOG_ERROR("sigaction()"); + if (ret) { + CWS_LOG_ERROR("sigaction(): %s", strerror(errno)); return 1; } diff --git a/src/server/server.c b/src/server/server.c index 19ab232..7390f3f 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,6 +32,10 @@ int cws_server_start(cws_config *config) { } int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sockfd < 0) { + CWS_LOG_ERROR("socket(): %s", strerror(errno)); + exit(EXIT_FAILURE); + } const int opt = 1; status = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt); @@ -46,7 +52,7 @@ int cws_server_start(cws_config *config) { status = listen(sockfd, CWS_SERVER_BACKLOG); if (status != 0) { - CWS_LOG_ERROR("listen(): %s", gai_strerror(status)); + CWS_LOG_ERROR("listen(): %s", strerror(status)); exit(EXIT_FAILURE); } @@ -77,7 +83,7 @@ void cws_server_loop(int sockfd, cws_config *config) { struct sockaddr_storage their_sa; socklen_t theirsa_size = sizeof their_sa; - cws_hashmap *clients = cws_hm_init(my_str_hash_fn, my_str_equal_fn, NULL, NULL); + cws_hashmap *clients = cws_hm_init(my_int_hash_fn, my_int_equal_fn, NULL, my_int_free_fn); int epfd = epoll_create1(0); cws_fd_set_nonblocking(sockfd); @@ -153,7 +159,6 @@ void cws_server_loop(int sockfd, cws_config *config) { /* Clean up everything */ free(revents); close(epfd); - cws_server_close_all_fds(clients); cws_hm_free(clients); CWS_LOG_INFO("Closing..."); } @@ -201,25 +206,42 @@ int cws_server_accept_client(int sockfd, struct sockaddr_storage *their_sa, sock return client_fd; } -void cws_server_close_all_fds(cws_hashmap *hashmap) { - /* TODO: fix this */ - - /*for (size_t i = 0; i < CWS_HASHMAP_SIZE; ++i) { - close(bucket[i].sockfd); - if (bucket[i].next != NULL) { - cws_bucket *p = bucket[i].next; - cws_bucket *next = p->next; - do { - close(p->sockfd); - p = next; - next = p != NULL ? p->next : NULL; - } while (p != NULL); - } - }*/ -} - void cws_server_close_client(int epfd, int client_fd, cws_hashmap *hashmap) { cws_epoll_del(epfd, client_fd); - /* TODO: cws_hm_remove() */ - close(client_fd); + cws_hm_remove(hashmap, &client_fd); +} + +SSL_CTX *cws_ssl_create_context() { + const SSL_METHOD *method; + SSL_CTX *ctx; + + method = TLS_server_method(); + ctx = SSL_CTX_new(method); + + if (!ctx) { + CWS_LOG_ERROR("SSL_CTX_new()"); + return NULL; + } + + return ctx; +} + +bool cws_ssl_configure(SSL_CTX *context, cws_config *config) { + int ret; + + ret = SSL_CTX_use_certificate_file(context, config->cert, SSL_FILETYPE_PEM); + if (ret <= 0) { + CWS_LOG_ERROR("SSL_CTX_use_certificate_file()"); + + return false; + } + + ret = SSL_CTX_use_PrivateKey_file(context, config->key, SSL_FILETYPE_PEM); + if (ret <= 0) { + CWS_LOG_ERROR("SSL_CTX_use_PrivateKey_file()"); + + return false; + } + + return true; } diff --git a/src/utils/utils.c b/src/utils/utils.c index f3371d4..87e8f5d 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "utils/colors.h" @@ -82,3 +83,21 @@ bool my_str_equal_fn(void *a, void *b) { } void my_str_free_fn(void *value) { free(value); } + +int my_int_hash_fn(void *key) { return *(int *)key; } + +bool my_int_equal_fn(void *a, void *b) { + int ai = *(int *)a; + int bi = *(int *)b; + + if (ai == bi) { + return true; + } + + return false; +} + +void my_int_free_fn(void *value) { + int fd = *(int *)value; + close(fd); +}