From 954bcb7e3e9185dd5dd612ec72fa7b8a3784baa3 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Sat, 29 Nov 2025 19:56:09 +0100 Subject: [PATCH] Add option for HTTPS clients to not verify the peer's certificate --- chttp.c | 26 ++++++++++++++++++++++---- chttp.h | 14 +++++++++++++- misc/amalg.py | 3 +++ src/client.c | 13 ++++++++++++- src/client.h | 7 +++++++ src/server.c | 2 +- src/socket.c | 11 +++++++++-- src/socket.h | 4 +++- 8 files changed, 70 insertions(+), 10 deletions(-) diff --git a/chttp.c b/chttp.c index 91e5353..b897a5b 100644 --- a/chttp.c +++ b/chttp.c @@ -2454,6 +2454,9 @@ static void socket_update(Socket *s) break; } + SSL_set_verify(s->ssl, s->dont_verify_cert + ? SSL_VERIFY_NONE : SSL_VERIFY_PEER, NULL); + AddressAndPort addr; if (s->num_addr > 1) addr = s->addrs[s->next_addr]; @@ -2937,7 +2940,8 @@ static int resolve_connect_targets(ConnectTarget *targets, #define MAX_CONNECT_TARGETS 16 int socket_connect(SocketManager *sm, int num_targets, - ConnectTarget *targets, bool secure, void *user) + ConnectTarget *targets, bool secure, bool dont_verify_cert, + void *user) { if (sm->num_used == sm->max_used) return HTTP_ERROR_UNSPECIFIED; @@ -2987,8 +2991,11 @@ int socket_connect(SocketManager *sm, int num_targets, s->server_secure_context = NULL; s->client_secure_context = NULL; s->ssl = NULL; - if (secure) + s->dont_verify_cert = false; + if (secure) { s->client_secure_context = &sm->client_secure_context; + s->dont_verify_cert = dont_verify_cert; + } #endif sm->num_used++; @@ -3819,6 +3826,17 @@ void http_request_builder_trace(HTTP_RequestBuilder builder, bool trace_bytes) conn->trace_bytes = trace_bytes; } +// TODO: comment +void http_request_builder_insecure(HTTP_RequestBuilder builder, + bool insecure) +{ + HTTP_ClientConn *conn = request_builder_to_conn(builder); + if (conn == NULL) + return; // Invalid builder + + conn->dont_verify_cert = insecure; +} + void http_request_builder_method(HTTP_RequestBuilder builder, HTTP_Method method) { @@ -4035,7 +4053,7 @@ int http_request_builder_send(HTTP_RequestBuilder builder) ConnectTarget target = url_to_connect_target(conn->url); bool secure = http_streq(conn->url.scheme, HTTP_STR("https")); - if (socket_connect(&client->sockets, 1, &target, secure, conn) < 0) + if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0) goto error; conn->state = HTTP_CLIENT_CONN_FLUSHING; @@ -4627,7 +4645,7 @@ void http_server_process_events(HTTP_Server *server, if (events[i].type == SOCKET_EVENT_DISCONNECT) { - http_server_conn_free(conn); + http_server_conn_free(conn); // TODO: what if this was in the ready queue? server->num_conns--; } else if (events[i].type == SOCKET_EVENT_READY) { diff --git a/chttp.h b/chttp.h index 0691528..a8cf645 100644 --- a/chttp.h +++ b/chttp.h @@ -1,3 +1,5 @@ +#ifndef HTTP_INCLUDED +#define HTTP_INCLUDED // cHTTP, an HTTP client and server library! // // This file was generated automatically. Do not modify directly. @@ -503,6 +505,7 @@ typedef struct { ClientSecureContext *client_secure_context; ServerSecureContext *server_secure_context; SSL *ssl; + bool dont_verify_cert; #endif } Socket; @@ -642,7 +645,8 @@ typedef struct { // one succedes. If secure=true, the socket uses TLS. // Returns 0 on success, -1 on error. int socket_connect(SocketManager *sm, int num_targets, - ConnectTarget *targets, bool secure, void *user); + ConnectTarget *targets, bool secure, bool dont_verify_cert, + void *user); int socket_recv(SocketManager *sm, SocketHandle handle, char *dst, int max); @@ -915,6 +919,9 @@ typedef struct { // TODO: comment bool trace_bytes; + // TODO: comment + bool dont_verify_cert; + // Allocated copy of the URL string HTTP_String url_buffer; @@ -1004,6 +1011,10 @@ void http_request_builder_set_user(HTTP_RequestBuilder builder, void http_request_builder_trace(HTTP_RequestBuilder builder, bool trace_bytes); +// TODO: comment +void http_request_builder_insecure(HTTP_RequestBuilder builder, + bool insecure); + // Set the method of the current request. This is the first // function of the request builder that the user must call. void http_request_builder_method(HTTP_RequestBuilder builder, @@ -1337,3 +1348,4 @@ void http_response_builder_send(HTTP_ResponseBuilder builder); // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //////////////////////////////////////////////////////////////////////////////////////// +#endif // HTTP_INCLUDED diff --git a/misc/amalg.py b/misc/amalg.py index 71350e6..ddedf2d 100644 --- a/misc/amalg.py +++ b/misc/amalg.py @@ -53,6 +53,8 @@ license = """ """ header = Amalgamator() +header.append_text("#ifndef HTTP_INCLUDED\n") +header.append_text("#define HTTP_INCLUDED\n") header.append_text(desc) header.append_file("src/includes.h") header.append_file("src/basic.h") @@ -64,6 +66,7 @@ header.append_file("src/cert.h") header.append_file("src/client.h") header.append_file("src/server.h") header.append_text(license) +header.append_text("#endif // HTTP_INCLUDED\n") header.save("chttp.h") source = Amalgamator() diff --git a/src/client.c b/src/client.c index fb307ff..786ec3d 100644 --- a/src/client.c +++ b/src/client.c @@ -197,6 +197,17 @@ void http_request_builder_trace(HTTP_RequestBuilder builder, bool trace_bytes) conn->trace_bytes = trace_bytes; } +// TODO: comment +void http_request_builder_insecure(HTTP_RequestBuilder builder, + bool insecure) +{ + HTTP_ClientConn *conn = request_builder_to_conn(builder); + if (conn == NULL) + return; // Invalid builder + + conn->dont_verify_cert = insecure; +} + void http_request_builder_method(HTTP_RequestBuilder builder, HTTP_Method method) { @@ -413,7 +424,7 @@ int http_request_builder_send(HTTP_RequestBuilder builder) ConnectTarget target = url_to_connect_target(conn->url); bool secure = http_streq(conn->url.scheme, HTTP_STR("https")); - if (socket_connect(&client->sockets, 1, &target, secure, conn) < 0) + if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0) goto error; conn->state = HTTP_CLIENT_CONN_FLUSHING; diff --git a/src/client.h b/src/client.h index ef5c4df..b3b142e 100644 --- a/src/client.h +++ b/src/client.h @@ -81,6 +81,9 @@ typedef struct { // TODO: comment bool trace_bytes; + // TODO: comment + bool dont_verify_cert; + // Allocated copy of the URL string HTTP_String url_buffer; @@ -170,6 +173,10 @@ void http_request_builder_set_user(HTTP_RequestBuilder builder, void http_request_builder_trace(HTTP_RequestBuilder builder, bool trace_bytes); +// TODO: comment +void http_request_builder_insecure(HTTP_RequestBuilder builder, + bool insecure); + // Set the method of the current request. This is the first // function of the request builder that the user must call. void http_request_builder_method(HTTP_RequestBuilder builder, diff --git a/src/server.c b/src/server.c index 5aa76c7..56707c9 100644 --- a/src/server.c +++ b/src/server.c @@ -229,7 +229,7 @@ void http_server_process_events(HTTP_Server *server, if (events[i].type == SOCKET_EVENT_DISCONNECT) { - http_server_conn_free(conn); + http_server_conn_free(conn); // TODO: what if this was in the ready queue? server->num_conns--; } else if (events[i].type == SOCKET_EVENT_READY) { diff --git a/src/socket.c b/src/socket.c index 4d93a52..ed196cb 100644 --- a/src/socket.c +++ b/src/socket.c @@ -524,6 +524,9 @@ static void socket_update(Socket *s) break; } + SSL_set_verify(s->ssl, s->dont_verify_cert + ? SSL_VERIFY_NONE : SSL_VERIFY_PEER, NULL); + AddressAndPort addr; if (s->num_addr > 1) addr = s->addrs[s->next_addr]; @@ -1007,7 +1010,8 @@ static int resolve_connect_targets(ConnectTarget *targets, #define MAX_CONNECT_TARGETS 16 int socket_connect(SocketManager *sm, int num_targets, - ConnectTarget *targets, bool secure, void *user) + ConnectTarget *targets, bool secure, bool dont_verify_cert, + void *user) { if (sm->num_used == sm->max_used) return HTTP_ERROR_UNSPECIFIED; @@ -1057,8 +1061,11 @@ int socket_connect(SocketManager *sm, int num_targets, s->server_secure_context = NULL; s->client_secure_context = NULL; s->ssl = NULL; - if (secure) + s->dont_verify_cert = false; + if (secure) { s->client_secure_context = &sm->client_secure_context; + s->dont_verify_cert = dont_verify_cert; + } #endif sm->num_used++; diff --git a/src/socket.h b/src/socket.h index 4838e31..c14834c 100644 --- a/src/socket.h +++ b/src/socket.h @@ -173,6 +173,7 @@ typedef struct { ClientSecureContext *client_secure_context; ServerSecureContext *server_secure_context; SSL *ssl; + bool dont_verify_cert; #endif } Socket; @@ -312,7 +313,8 @@ typedef struct { // one succedes. If secure=true, the socket uses TLS. // Returns 0 on success, -1 on error. int socket_connect(SocketManager *sm, int num_targets, - ConnectTarget *targets, bool secure, void *user); + ConnectTarget *targets, bool secure, bool dont_verify_cert, + void *user); int socket_recv(SocketManager *sm, SocketHandle handle, char *dst, int max);