- Added secure_state_open(): hardened file open with O_CLOEXEC, O_NOFOLLOW, mode 0600, regular-file and ownership checks. Prevents symlink attacks, TOCTOU races, and world-writable temp files. - Replaced all fopen() calls for temp state files with secure_state_open() + fdopen() across hot reload, compile-restart, and rebuild paths. - Hardened TLS initialization: enforces minimum TLS 1.2, disables compression, checks SSL_CTX_set_default_verify_paths() return value. - CMake compiler/linker hardening: -Wformat=2, -Wstrict-prototypes, -fstack-protector-strong, _FORTIFY_SOURCE=3, RELRO, noexecstack. - Added !calc input validation: max 256 chars, numeric-only characters. - Added !stock symbol validation: alphanumerics plus .-^= only. - Fixed !quit, !reload, !restart to require channel context (DMs rejected). - Fixed log timestamp format: %y (2-digit) to %Y (4-digit year). - Fixed asprintf return value check in !forecast error paths. - Fixed !reload fork-in-place mode: only saves TLS state when exec_new=1. - Cleaned up reload state file on failure and in fork child. - Fixed git SSH-to-HTTPS URL conversion in !gitlog and !changelog. - AI plan mode no longer passes --dangerously-skip-permissions. - Added IRC buffer overflow protection: oversized lines are dropped. - Added doc comments to ZYNK_RELOAD_FILE, secure_state_open(), RateLimitEntry, and rate_limits.
109 lines
3 KiB
C
109 lines
3 KiB
C
#ifndef TLS_H
|
|
#define TLS_H
|
|
|
|
#include <openssl/ssl.h>
|
|
#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
|