zynk/tls.h
hanez 72f7812630 Secure file ops, TLS hardening, input validation, security docs. (0.40.7)
- 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.
2026-07-24 03:21:49 +02:00

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