Skip to content

feat: S12.28 surface TLS peer-hostname verification when ServerName is NULL#534

Merged
DavidCozens merged 1 commit into
mainfrom
feat/s12-28-tls-hostname-verification
Jun 4, 2026
Merged

feat: S12.28 surface TLS peer-hostname verification when ServerName is NULL#534
DavidCozens merged 1 commit into
mainfrom
feat/s12-28-tls-hostname-verification

Conversation

@DavidCozens

@DavidCozens DavidCozens commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Purpose

Closes #529 — a High-severity finding from the pre-0.1.0 security audit. Both TLS adapters verified the certificate chain against the CA bundle, but bound the peer identity to the certificate only when ServerName was configured. With ServerName == NULL the handshake completed against any certificate chaining to a trusted CA — a silent, MITM-class default with no diagnostic emitted.

Change Description

Make the unverified-peer case observable, per the model agreed with David (NULL warns, "" opts out):

  • ServerName == NULL → emit SolidSyslog_Error(WARNING, …, BAD_CONFIG, *_SERVER_NAME_NOT_SET) and still connect chain-only. Preserves the closed-network / IP-pinning use case while making it observable rather than silent.
  • ServerName == "" → deliberate opt-out: connect chain-only, no diagnostic. The explicit "I have no name to verify against" signal.
  • Non-empty ServerName → SNI + identity check, unchanged.

Decisions worth noting beyond the diff:

  • Reused the existing *_SERVER_NAME_NOT_SET detail at WARNING severity rather than adding a new enum value — the name fits the NULL case, and severity is the discriminator (ERROR = a provided name couldn't be applied → unwound; WARNING = no name → connected unverified). No public error-enum change.
  • "No DNS" ≠ "no hostname verification" — identity binding (SSL_set1_host / mbedtls_ssl_set_hostname) is a string check against the cert and needs no DNS. An IP-pinned target can still set ServerName to the name (or IP SAN) on its cert and get full MITM protection. Documented in both ServerName header comments and docs/integrating-mbedtls.md.
  • Behaviour is identical across the OpenSSL and mbedTLS adapters.

Test Evidence

TDD, mirrored across both adapters. New tests per adapter:

  • OpenWarnsWhenServerNameIsNull — handler fires once, WARNING / BAD_CONFIG / *_SERVER_NAME_NOT_SET.
  • OpenStillConnectsWhenServerNameIsNull — Open returns true, transport not closed.
  • OpenDoesNotWarnWhenServerNameIsEmpty / OpenSkipsHostnameSetupWhenServerNameIsEmpty / OpenConnectsWhenServerNameIsEmpty — the "" opt-out.

A few existing handshake-failure tests now set a ServerName so the new NULL-warning doesn't double-fire alongside their single expected error (test-only fallout from the behaviour change).

Local runs (Tier A): OpenSSL SolidSyslogTlsStream group green (135 tests) in the gcc container; mbedTLS SolidSyslogMbedTlsStream group green (54 tests) in freertos-host. MISRA suppressions renumbered for the shifted mbedTLS 11.5 cast sites and verified against the formatted source.

Areas Affected

  • Platform/OpenSsl/Source/SolidSyslogTlsStream.c, Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c
  • Platform/OpenSsl/Interface/SolidSyslogTlsStream.h, Platform/MbedTls/Interface/SolidSyslogMbedTlsStream.h (ServerName doc contract)
  • docs/integrating-mbedtls.md, misra_suppressions.txt, tests, DEVLOG

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • TLS connections now emit a warning when hostname verification cannot be performed due to missing server name configuration.
    • Added explicit opt-out for hostname verification warnings via empty string configuration.
  • Documentation

    • Updated TLS integration documentation to clarify hostname verification behavior across different server name configurations.

…s NULL

Both TLS adapters (OpenSSL, mbedTLS) bound the peer identity to the certificate
only when ServerName was set, so a NULL ServerName completed the handshake
against any cert chaining to a trusted CA — a silent, MITM-class default with
no diagnostic. Make the unverified-peer case observable:

- ServerName == NULL -> WARNING (BAD_CONFIG / *_SERVER_NAME_NOT_SET), still
  connect chain-only (preserves the closed-network / IP-pinning use case).
- ServerName == "" -> deliberate opt-out: connect chain-only, no diagnostic.
- Non-empty ServerName -> SNI + identity check, unchanged.

Reuses the existing *_SERVER_NAME_NOT_SET detail at WARNING severity; no public
error-enum change. Documents that "no DNS" does not force NULL ServerName in
both header comments and docs/integrating-mbedtls.md.

Closes #529

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55dcdeab-2045-4c1f-b17a-3744d144e2f8

📥 Commits

Reviewing files that changed from the base of the PR and between 298e20e and a953695.

📒 Files selected for processing (9)
  • DEVLOG.md
  • Platform/MbedTls/Interface/SolidSyslogMbedTlsStream.h
  • Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c
  • Platform/OpenSsl/Interface/SolidSyslogTlsStream.h
  • Platform/OpenSsl/Source/SolidSyslogTlsStream.c
  • Tests/MbedTls/SolidSyslogMbedTlsStreamTest.cpp
  • Tests/SolidSyslogTlsStreamTest.cpp
  • docs/integrating-mbedtls.md
  • misra_suppressions.txt

📝 Walkthrough

Walkthrough

The PR implements decision policy S12.28 for TLS peer-hostname verification when ServerName is NULL. Both OpenSSL and mbedTLS adapters now emit a WARNING diagnostic and allow chain-only connection instead of silently skipping verification. Empty string ServerName becomes an explicit opt-out with no diagnostic. Non-empty names continue to verify as before. All changes are documented and tested across both adapters.

Changes

TLS peer-hostname verification diagnostic for NULL ServerName

Layer / File(s) Summary
Specification and documentation of three ServerName states
DEVLOG.md, Platform/MbedTls/Interface/SolidSyslogMbedTlsStream.h, Platform/OpenSsl/Interface/SolidSyslogTlsStream.h, docs/integrating-mbedtls.md
DEVLOG entry records story S12.28 and the decision to warn-and-continue on NULL ServerName. Interface comments specify three behaviors: non-empty ServerName triggers SNI + peer identity verification (SAN/CN), NULL connects chain-only with WARNING diagnostic, and "" is an explicit opt-out with no diagnostic. Integration docs clarify the distinction between DNS availability, IP-pinning, and deliberate opt-out.
mbedTLS adapter ServerName configuration logic
Platform/MbedTls/Source/SolidSyslogMbedTlsStream.c, misra_suppressions.txt
MbedTlsStream_ConfigureExpectedHostname replaces the prior ServerName != NULL guard with three explicit paths: NULL emits MBEDTLSSTREAM_ERROR_SERVER_NAME_NOT_SET WARNING and allows handshake; non-empty strings call mbedtls_ssl_set_hostname and report configuration errors on failure; empty string is a no-op with no diagnostic. MISRA suppression line numbers are updated to reflect refactored code positions.
OpenSSL adapter ServerName configuration logic
Platform/OpenSsl/Source/SolidSyslogTlsStream.c
TlsStream_ConfigureExpectedHostname refactors to handle NULL ServerName by emitting TLSSTREAM_ERROR_SERVER_NAME_NOT_SET WARNING without treating it as a configuration error; non-empty strings set both SSL_set_tlsext_host_name and SSL_set1_host, reporting errors if either fails; empty string is a deliberate no-op with no diagnostic. Identical policy to mbedTLS adapter.
mbedTLS test coverage for ServerName states and error isolation
Tests/MbedTls/SolidSyslogMbedTlsStreamTest.cpp
New tests verify NULL ServerName triggers a warning via ErrorHandlerFake (category SOLIDSYSLOG_CAT_BAD_CONFIG, detail MBEDTLSSTREAM_ERROR_SERVER_NAME_NOT_SET) while open succeeds, and empty string suppresses warning while skipping hostname setup and still succeeding. Existing handshake failure/timeout/hard-error tests are updated to set ServerName and recreate the handle, isolating those error paths from ServerName diagnostics.
OpenSSL test coverage for ServerName states and error isolation
Tests/SolidSyslogTlsStreamTest.cpp
New tests verify NULL ServerName emits warning (SOLIDSYSLOG_CAT_BAD_CONFIG / TLSSTREAM_ERROR_SERVER_NAME_NOT_SET) while open succeeds, and empty string suppresses diagnostic while skipping hostname setup and succeeding. Handshake/timeout/hard-failure tests are updated to set ServerName and recreate the stream, ensuring those error paths are exercised without ServerName warning interference.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • DavidCozens/solid-syslog#440: Both PRs modify MbedTlsStream_ConfigureExpectedHostname and the MBEDTLSSTREAM_ERROR_SERVER_NAME_NOT_SET error path around ServerName hostname-configuration logic.
  • DavidCozens/solid-syslog#442: Both PRs update TLS hostname-configuration logic (TlsStream_ConfigureExpectedHostname / MbedTlsStream_ConfigureExpectedHostname) with changes to ServerName handling and error emission within open/configure failure flows.
  • DavidCozens/solid-syslog#183: Both PRs modify OpenSSL's hostname/peer-identity configuration path in TlsStream_ConfigureExpectedHostname, with #183 hardening return-value checks and this PR changing ServerName branching and diagnostic policy.

Poem

🐰 A rabbit hops through certs with care,
When ServerName is NULL—beware!
A WARNING hops, diagnostics clear,
No silent MITM, just honest peer.
Three paths now dance in harmony,
OpenSSL and mbedTLS agree. 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: making TLS peer-hostname verification observable when ServerName is NULL, which is the core security issue addressed.
Description check ✅ Passed The PR description is comprehensive, covering Purpose (links to #529), Change Description (three-way behavior), Test Evidence (new tests added), and Areas Affected (specific files).
Linked Issues check ✅ Passed The implementation meets issue #529 acceptance criteria: NULL ServerName is now observable (emits WARNING), ServerName-set path unchanged, behavior identical across adapters, and changes are TDD-driven with new test coverage.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the issue #529 requirement. Updates to DEVLOG, header documentation, source implementations, tests, MISRA suppressions, and integration docs are all necessary to fully address the security finding.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/s12-28-tls-hostname-verification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1438 passed)
   🚦   build-freertos-host-tdd-plustcp: 100% successful (✔️ 1788 passed)
   🚦   build-linux-clang: 100% successful (✔️ 1372 passed)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1372 passed)
   🚦   integration-linux-openssl: 100% successful (✔️ 16 passed)
   🚦   integration-linux-mbedtls: 100% successful (✔️ 14 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 16 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 48 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 88% successful (✔️ 45 passed, 🙈 6 skipped)
   🚦   bdd-freertos-qemu-plustcp: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   bdd-freertos-qemu-lwip: 86% successful (✔️ 44 passed, 🙈 7 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 1227 passed)
   🚦   build-linux-tunable-override: 100% successful (✔️ 1372 passed)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

@DavidCozens DavidCozens merged commit f081e97 into main Jun 4, 2026
27 checks passed
@DavidCozens DavidCozens deleted the feat/s12-28-tls-hostname-verification branch June 4, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S12.28: TLS peer-hostname verification not enforced when ServerName is NULL

1 participant