#ifndef TLS_H #define TLS_H #include #include "zynk.h" extern int tls_verify; /* ---- TLS ---- */ static SSL_CTX *tls_ctx; /* * tls_init - Initialize the OpenSSL library and create a TLS context. * * Calls SSL_library_init() and SSL_load_error_strings() for OpenSSL setup, * creates a new SSL_CTX using the TLS client method, loads default CA * certificates for peer verification, and configures the verify mode * based on the global tls_verify flag. * * Returns: 0 on success, -1 if context creation fails. */ static int tls_init(void) { SSL_library_init(); SSL_load_error_strings(); tls_ctx = SSL_CTX_new(TLS_client_method()); if (!tls_ctx) return -1; if (SSL_CTX_set_min_proto_version(tls_ctx, TLS1_2_VERSION) != 1) { SSL_CTX_free(tls_ctx); tls_ctx = NULL; return -1; } SSL_CTX_set_options(tls_ctx, SSL_OP_NO_COMPRESSION); if (tls_verify && SSL_CTX_set_default_verify_paths(tls_ctx) != 1) { SSL_CTX_free(tls_ctx); tls_ctx = NULL; return -1; } SSL_CTX_set_verify(tls_ctx, tls_verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); return 0; } /* * tls_handshake - Perform a TLS handshake on an established TCP connection. * * Creates a new SSL object, associates it with the session's file descriptor * and hostname (for SNI), then performs the handshake. Temporarily disables * O_NONBLOCK on the fd since SSL_connect needs blocking I/O, then restores * the original flags. If tls_verify is enabled, validates the server's * certificate against the system CA store. * * Parameters: * s - The IRC session with a valid fd and host. * * Returns: 0 on successful handshake, -1 on failure (SSL object is freed). */ static int tls_handshake(Session *s) { if (!tls_ctx) return -1; s->ssl = SSL_new(tls_ctx); if (!s->ssl) return -1; SSL_set_fd(s->ssl, s->fd); SSL_set_tlsext_host_name(s->ssl, s->host); if (tls_verify) SSL_set1_host(s->ssl, s->host); int fl = fcntl(s->fd, F_GETFL, 0); fcntl(s->fd, F_SETFL, fl & ~O_NONBLOCK); int r = SSL_connect(s->ssl); fcntl(s->fd, F_SETFL, fl | O_NONBLOCK); if (r != 1) { SSL_free(s->ssl); s->ssl = NULL; return -1; } if (tls_verify && SSL_get_verify_result(s->ssl) != X509_V_OK) { SSL_free(s->ssl); s->ssl = NULL; return -1; } return 0; } /* * tls_cleanup - Shut down and free the SSL connection for a session. * * Performs SSL_shutdown() to send the TLS close_notify alert (if the * connection is still active), then frees the SSL object. Safe to call * when s->ssl is NULL (no-op). * * Parameters: * s - The IRC session whose SSL connection to tear down. * * Returns: void. */ static void tls_cleanup(Session *s) { if (!s->ssl) return; SSL_shutdown(s->ssl); SSL_free(s->ssl); s->ssl = NULL; } /* * tls_ctx_cleanup - Free the global TLS context. * * Calls SSL_CTX_free() on the global tls_ctx and sets it to NULL. * Should be called during shutdown after all sessions are cleaned up. * * Returns: void. */ static void tls_ctx_cleanup(void) { if (tls_ctx) { SSL_CTX_free(tls_ctx); tls_ctx = NULL; } } #endif