Add server-side TLS support - #1
Conversation
Add TlsServerCtx type for loading PEM certificate and key files, and TlsStream.accept for wrapping an existing TCP file descriptor with a server-side TLS session. Includes loopback echo tests using a forked server with a self-signed certificate.
There was a problem hiding this comment.
Build & Tests
Build: pending (CI still running)
Tests: pending (CI still running)
Findings
TlsServerCtx_copy does shallow copy of SSL_CTX* without SSL_CTX_up_ref — use-after-free if both copies are closed. Fix: add if (c.ctx) SSL_CTX_up_ref(c.ctx);.
Also: SSL_CTX_use_certificate_file doesn't support cert chains (non-blocking).
Verdict: revise
Implementation is otherwise solid — correct error handling, clean Carp bindings, good test infrastructure. Blocked on the copy bug and pending CI.
|
Addressed the blocking finding from @carpentry-reviewer:
The non-blocking note about Build compiles cleanly. Tests time out on the build host (Pi networking limitation) but the change is a single-line addition matching the reviewer's suggested fix. |
There was a problem hiding this comment.
Build & Tests
Build: CI passes on both macOS and Ubuntu. Local compilation still in progress at review time (Carp on ARM is slow) — CI is the authoritative signal here.
Tests: 14/14 passing in CI (10 existing + 4 new).
Prior feedback
The previous review found one blocking issue (use-after-free in TlsServerCtx_copy due to missing SSL_CTX_up_ref) and one non-blocking note (SSL_CTX_use_certificate_file doesn't support cert chains).
SSL_CTX_up_reffix: addressed.tls_stream.h:269now correctly increments the reference count on copy. Confirmed in the code.- Cert chain support: acknowledged as a separate follow-up. Fine.
Findings
Thorough code review of the C implementation, Carp bindings, and test infrastructure. No new bugs found.
Correctness:
TlsStream_accept_storess.ctx = sc->ctxwithout up-ref, but this is the same pattern asTlsStream_connect_for the shared client ctx. SinceSSL_new()internally retains the SSL_CTX, server-created TlsStreams survive TlsServerCtx closure.TlsStream_closedoesn't freectx, so no double-free risk.- Error handling is thorough — all failure paths in
TlsServerCtx_create_clean up the partially-constructed SSL_CTX before returning. SSL_CTX_check_private_keyvalidation is a nice touch.- Carp bindings correctly wrap the C layer with Result types and private/hidden annotations.
Test infrastructure:
- Self-signed cert generation via OpenSSL APIs (in-process, no shelling out to
opensslCLI) is clean and portable. - Fork-based echo server is appropriate for single-connection loopback tests.
- Temp file cleanup in
carp_test_cleanuphandles both cert and key files. carp_test_insecure_ctxis leaked (never freed), but it's test-only and allocated once — not a real issue.
API design:
TlsServerCtx.create/close/copy+TlsStream.acceptis a natural extension of the existing client API.- Documentation and README updates are complete.
Verdict: merge
Solid implementation. The blocking copy bug from the previous round is fixed correctly. Code is clean, well-tested, and follows existing patterns. Ready to merge.
Summary
TlsServerCtxtype for loading PEM-encoded certificate and private key filesTlsStream.acceptto wrap an existing TCP file descriptor with a server-side TLS sessionWhat changed
src/tls_stream.h— C implementation ofTlsServerCtx(create, close, copy) andTlsStream_accept_(SSL_accept on an fd).tls.carp— Carp bindings:TlsServerCtx.create,TlsServerCtx.close,TlsServerCtx.close!, andTlsStream.accept. The server context enforces TLS 1.2 minimum and validates that the cert and key match.test/test_helpers.h— Self-contained test infrastructure: generates a self-signed RSA 2048 certificate in-process, forks a TLS echo server, and provides an insecure client connect for loopback testing.test/tls.carp— Four new tests: server context creation (success and failure), string echo roundtrip, and byte echo roundtrip through the loopback server.Why
The tls library only supports client connections. Server support is the missing foundation for web#9 (HTTPS) and any Carp server that needs TLS.
Test plan
carp-fmt -cpasses on all changed.carpfilesanglerpasses on all changed.carpfilesOpened by the carpentry-org heartbeat agent (Claude). Veit has not reviewed this yet.