summaryrefslogtreecommitdiffstats
path: root/src/tls.c
diff options
context:
space:
mode:
authorGab Virebent <gab@virebent.art>2026-06-26 19:20:00 +0200
committerGab Virebent <gab@virebent.art>2026-06-26 19:20:00 +0200
commitfb48d1308d2f63f8e9b23c5d1d921783fa0dacbe (patch)
treeceecce2f057cd4ea1e6724305fcd52915939c419 /src/tls.c
parent41c4bfecc770ea7c914e845e4ac3792cb4a473d3 (diff)
downloadgmnisrv-fb48d1308d2f63f8e9b23c5d1d921783fa0dacbe.tar.gz
gmnisrv-fb48d1308d2f63f8e9b23c5d1d921783fa0dacbe.tar.xz
gmnisrv-fb48d1308d2f63f8e9b23c5d1d921783fa0dacbe.zip
Serve CA full chain (Let's Encrypt), TLS 1.3, fix handshake buffer overflowHEADmain
- tls.c/config.h: read full PEM chain into STACK_OF(X509), send via SSL_set1_chain - tls.c: minimum protocol TLS 1.2 -> TLS 1.3 - server.c: drain handshake output via local buffer loop instead of staging into the fixed 4 KB client buffer (a full CA chain overflowed it -> assert) - FORK.md: describe the fork
Diffstat (limited to 'src/tls.c')
-rw-r--r--src/tls.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/tls.c b/src/tls.c
index 02d7ab7..8f9bb81 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -140,13 +140,24 @@ tls_host_init(struct gmnisrv_tls *tlsconf, struct gmnisrv_host *host)
}
X509 *x509 = PEM_read_X509(xf, NULL, NULL, NULL);
- fclose(xf);
if (!x509) {
+ fclose(xf);
server_error("error loading certificate from %s", crtpath);
fclose(kf);
return 1;
}
+ // Read any remaining certificates in the PEM file as the intermediate
+ // chain so CA-signed certs (e.g. Let's Encrypt fullchain.pem) are sent
+ // to the client for proper validation.
+ STACK_OF(X509) *chain = sk_X509_new_null();
+ X509 *ca;
+ while ((ca = PEM_read_X509(xf, NULL, NULL, NULL)) != NULL) {
+ sk_X509_push(chain, ca);
+ }
+ ERR_clear_error();
+ fclose(xf);
+
EVP_PKEY *pkey = PEM_read_PrivateKey(kf, NULL, NULL, NULL);
fclose(kf);
if (!pkey) {
@@ -160,12 +171,15 @@ tls_host_init(struct gmnisrv_tls *tlsconf, struct gmnisrv_host *host)
assert(r == 1);
if (day < 0 || sec < 0) {
server_log("%s certificate is expired", host->hostname);
+ sk_X509_pop_free(chain, X509_free);
goto generate;
}
host->x509 = x509;
host->pkey = pkey;
- server_log("loaded certificate for %s", host->hostname);
+ host->chain = chain;
+ server_log("loaded certificate for %s (%d chain cert(s))",
+ host->hostname, sk_X509_num(chain));
return 0;
generate:
@@ -181,7 +195,7 @@ tls_init(struct gmnisrv_config *conf)
conf->tls.ssl_ctx = SSL_CTX_new(TLS_server_method());
assert(conf->tls.ssl_ctx);
- int r = SSL_CTX_set_min_proto_version(conf->tls.ssl_ctx, TLS1_2_VERSION);
+ int r = SSL_CTX_set_min_proto_version(conf->tls.ssl_ctx, TLS1_3_VERSION);
assert(r == 1);
r = SSL_CTX_set_cipher_list(conf->tls.ssl_ctx,
@@ -238,4 +252,7 @@ tls_set_host(SSL *ssl, struct gmnisrv_host *host)
{
SSL_use_certificate(ssl, host->x509);
SSL_use_PrivateKey(ssl, host->pkey);
+ if (host->chain && sk_X509_num(host->chain) > 0) {
+ SSL_set1_chain(ssl, host->chain);
+ }
}