Skip to content

Commit 9efe534

Browse files
committed
TASK-194: Close TLS publication and rotation findings and mark complete
1 parent 96bb149 commit 9efe534

11 files changed

Lines changed: 1061 additions & 821 deletions

File tree

‎scripts/lib/v3_public_tls_profiles.py‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,30 @@ def probe(port, version='13', kind='psk', host='a.example', alpn='http/1.1', ide
269269
args = [str(client), str(port), version, 'certificate', 'a.example', 'http/1.1', 'identity', 'interactive', str(fixtures)]
270270
with Consumer(args, directory, env, directory / ('rotation-session-' + version + '.json')) as session:
271271
old = json.loads(session.line())
272-
command(child, 'rotate', 'ROTATED')
273-
session.process.stdin.write(b'next b.example\n'); session.process.stdin.flush()
274-
fresh = json.loads(session.line())
275-
check(fresh['connected'] and fresh['reused'] == 0 and fresh['certificate_messages'] == 1
276-
and fresh['certificate_sha256'] != old['certificate_sha256'], 'old session bypassed replacement')
272+
session.process.stdin.write(b'next a.example\n'); session.process.stdin.flush()
273+
resumed = json.loads(session.line())
274+
check(resumed['connected'] and resumed['reused'] == 1 and resumed['certificate_messages'] == 0
275+
and resumed['certificate_sha256'] == old['certificate_sha256'], 'same-host session did not resume before rotation')
276+
with connect(port, context(fixtures, version)) as established:
277+
for turn in range(2):
278+
established.sendall(b'GET /installed HTTP/1.1\r\nHost: a.example\r\nConnection: keep-alive\r\n\r\n')
279+
body, pending, head = response(established)
280+
check(head.startswith('HTTP/1.1 200 ') and body == b'profile-ok\n\n' and not pending,
281+
'replacement disrupted established connection')
282+
if turn == 0:
283+
command(child, 'rotate-same-host', 'ROTATED')
284+
session.process.stdin.write(b'next a.example\n'); session.process.stdin.flush()
285+
fresh = json.loads(session.line())
286+
check(fresh['connected'] and fresh['reused'] == 0 and fresh['certificate_messages'] == 1
287+
and fresh['certificate_sha256'] != old['certificate_sha256'], 'old same-host session bypassed replacement')
288+
expected = hashlib.sha256(ssl.PEM_cert_to_DER_cert((fixtures / 'a-replacement.pem').read_text())).hexdigest()
289+
check(fresh['certificate_sha256'] == expected and fresh['alpn'] == old['alpn'] == 'http/1.1',
290+
'same-host replacement material or ALPN differs')
277291
session.process.stdin.write(b'quit\n'); session.process.stdin.flush()
278292
session.process.wait(timeout=3)
279293
child.stop()
280-
rows.append(dict(case='certificate_rotation_rejects_old_session_' + version, old=old, fresh=fresh))
294+
rows.append(dict(case='certificate_rotation_rejects_old_session_' + version, old=old, resumed=resumed, fresh=fresh,
295+
endpoint=['127.0.0.1', port], sni='a.example', established_requests=2))
281296
with launch('certificate') as child:
282297
port = child.port()
283298
args = [str(client), str(port), '13', 'certificate', 'a.example', 'http/1.1', 'identity', 'hold-acme', str(fixtures)]

‎specs/architecture/v3/TASK-194-implementation-evidence.md‎

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,30 @@ Behavioral RED preceded production changes: `initial-mtls-red.log` observed exis
1111
| Frozen owner lane | Programs | Tests | Checks | Failures |
1212
| --- | ---: | ---: | ---: | ---: |
1313
| Normal TLS-off | 18 | 289 | 3165 | 0 |
14-
| Normal TLS-on | 37 | 417 | 6404 | 0 |
14+
| Normal TLS-on | 37 | 418 | 6414 | 0 |
1515
| ASan/UBSan TLS-off | 18 | 289 | 3165 | 0 |
16-
| ASan/UBSan TLS-on | 37 | 417 | 6404 | 0 |
16+
| ASan/UBSan TLS-on | 37 | 418 | 6414 | 0 |
1717
| TSan TLS-off | 18 | 289 | 3163 | 0 |
18-
| TSan TLS-on | 37 | 417 | 6402 | 0 |
18+
| TSan TLS-on | 37 | 418 | 6412 | 0 |
1919

20-
`build/task194/owners-final.json` records exact suite names, counts, commands and log hashes; standalone header programs are distinguished from counted suites. Normal/ASan have zero skipped assertions. Each TSan lane retains one existing allocation-count-only exclusion in `request_lifecycle::zero_hook_commit_allocates_nothing`; functional commit assertions execute. Root explicitly confirmed the settled TASK-186/188 allocator-ownership boundary rather than changing unrelated guards. Normal/ASan execute the allocation counts. The unchanged external-readiness allocator-fault suite uses executable-specific Clang18 `-shared-libsan` linkage after static-runtime strong-symbol collision; all27 tests/491 checks execute with zero skips. Shared runtime identity/resolution and actual instrumentation symbols are retained in `tsan-adapter-runtime-graph.log`.
20+
`build/task194/owners-repair1.json` records refreshed TLS-on suite names, counts, commands and log hashes; `repair-off-audit/receipt.json` supports reuse of the TLS-off owners in `owners-final.json` after current-source no-op builds, identical compiled objects/libraries and compiler dependency closures excluding all repaired sources; standalone header programs are distinguished from counted suites. Normal/ASan have zero skipped assertions. Each TSan lane retains one existing allocation-count-only exclusion in `request_lifecycle::zero_hook_commit_allocates_nothing`; functional commit assertions execute. Root explicitly confirmed the settled TASK-186/188 allocator-ownership boundary rather than changing unrelated guards. Normal/ASan execute the allocation counts. The unchanged external-readiness allocator-fault suite uses executable-specific Clang18 `-shared-libsan` linkage after static-runtime strong-symbol collision; all27 tests/491 checks execute with zero skips. Shared runtime identity/resolution and actual instrumentation symbols are retained in `tsan-adapter-runtime-graph.log`.
2121

2222
ASan/UBSan runs with nonrecovering diagnostics, `detect_leaks=1`, `detect_stack_use_after_return=1`, use-after-scope enabled and halt-on-error. TSan runs outside ptrace with halt-on-error and no suppressions. Library and installed public server consumers are instrumented; independent provider-only clients remain separately identified tooling.
2323

2424
| Frozen installed public lane | Receipt directory | Shared/static × managed/external |
2525
| --- | --- | --- |
26-
| Normal TLS-on | `public-normal-on-final5` | 4 × 82 scenarios |
27-
| ASan/UBSan TLS-on | `public-asan-on-final2` | 4 × 82 scenarios |
28-
| TSan TLS-on | `public-tsan-on-final5` | 4 × 82 scenarios |
29-
| Normal TLS-off | `public-normal-off-final3` | 4 same-source cells |
30-
| ASan/UBSan TLS-off | `public-asan-off-final3` | 4 same-source cells |
31-
| TSan TLS-off | `public-tsan-off-final3` | 4 same-source cells |
26+
| Normal TLS-on | `public-normal-on-repair1` | 4 × 82 scenarios |
27+
| ASan/UBSan TLS-on | `public-asan-on-repair1` | 4 × 82 scenarios |
28+
| TSan TLS-on | `public-tsan-on-repair1` | 4 × 82 scenarios |
29+
| Normal TLS-off | `public-normal-off-repair1` | 4 same-source cells |
30+
| ASan/UBSan TLS-off | `public-asan-off-repair2` | 4 same-source cells |
31+
| TSan TLS-off | `public-tsan-off-repair1` | 4 same-source cells |
3232

33-
All six receipts pin the same source identity `19beacd1aa4b15b5732c914d189d923994146dcc73c2ea27e53e5785d903ea8a`. TLS-off cells execute the original14 configuration checks plus five public runtime/ACME/key checks. The 984 TLS-on scenario executions retain all23 TASK-193 cases and add59 explicit authentication/retirement/rotation/ACME/example cases. Public server applications compile outside the source/build tree against installed headers/pkg-config without provider/private headers or `HTTPSERVER_COMPILATION`. Shared/static link graphs, dependency files, link maps, library/header/compiler/client/fixture identities are retained. The independent OpenSSL client includes no libhttpserver headers and its runtime graph excludes libhttpserver.
33+
All six receipts pin the same source identity `0656f8818c550af469b2c1fe614a4f57ec3ca560f28a88de0022de56a59179b0`. TLS-off cells execute the original14 configuration checks plus five public runtime/ACME/key checks. The 984 TLS-on scenario executions retain all23 TASK-193 cases and add59 explicit authentication/retirement/rotation/ACME/example cases. Public server applications compile outside the source/build tree against installed headers/pkg-config without provider/private headers or `HTTPSERVER_COMPILATION`. Shared/static link graphs, dependency files, link maps, library/header/compiler/client/fixture identities are retained. The independent OpenSSL client includes no libhttpserver headers and its runtime graph excludes libhttpserver.
3434

3535
Independent TLS1.2/1.3 mTLS tests verify chain/hostname, actual fingerprints in both exchange and request hook, complete body/ALPN, valid/absent/untrusted clients and zero handler entry on rejection. Bound profile downgrades fail; multiple leases and concurrent bind/replace have deterministic public regressions. PSK witnesses assert actual version/cipher/ALPN/body, selected host/generation/finite callback deadline and version translation, exact binary1.3 identity, empty/oversized keys, oversized identities and redacted exception failure. Held callbacks outlive timeout/peer close/stop/drain; cancellation and late accepted keys never route. Caller handles and input material are dropped while a held callback remains alive. Fixed active/queued capacity survives four rotations, queued expiry never enters the callback, and capacity recovers after actual retirement. Healthy handlers acknowledge stop/drain while another callback remains blocked; explicit retirement reports timeout until release and callback self-wait returns would_deadlock. Two servers sharing a runtime remain independent when one stops.
3636

37-
Ordinary same-host/generation TLS1.2/1.3 session reuse is proven with reuse flags and omitted certificate messages. Host/store/replacement isolation requires fresh full certificate exchange. An accepted incomplete handshake retains its old certificate through replacement; an established keepalive socket remains useful while fresh sockets select the new certificate. The installed listener example serves three complete held-connection requests plus two verified fresh requests across valid and rejected replacement. External PSK and ACME disable ticket/session resumption. Real TLS1.3 early request bytes are transmitted by the independent client, rejected by the server, and never cause an extra handler invocation.
37+
Ordinary same-host/generation TLS1.2/1.3 session reuse is proven with reuse flags and omitted certificate messages. Host/store isolation remains separately tested. Replacement now uses a distinct trusted certificate valid for the original `a.example` SNI: the independent client retains its original session while proving reuse before publication at the same endpoint and ALPN, then requires reused=0, a full Certificate message and the exact replacement fingerprint. An established connection completes requests before and after that publication in both TLS versions. All twelve installed TLS-on cells execute these witnesses. An accepted incomplete handshake retains its old certificate through replacement; an established keepalive socket remains useful while fresh sockets select the new certificate. The installed listener example serves three complete held-connection requests plus two verified fresh requests across valid and rejected replacement. External PSK and ACME disable ticket/session resumption. Real TLS1.3 early request bytes are transmitted by the independent client, rejected by the server, and never cause an extra handler invocation.
3838

3939
ACME selection uses authentic `127.0.0.1:443`: exact/canonical SNI and sole `acme-tls/1` present the supplied certificate fingerprint, sole DNS SAN and unique critical digest DER/value. Wrong/absent SNI, wrong port, mixed/no/HTTP ALPN cannot select it. Normal HTTP stays chain/hostname verified. Eighteen malformed SAN/digest/certificate/key/expiry candidates reject and preserve the installed challenge; encrypted/malformed/mismatched keys are included. Actual absolute expiry rejects fresh handshakes; removal is canonical/idempotent, selected incomplete challenge handshakes remain pinned, and three concurrent normal/publish/remove writers finish coherently. Normal mTLS/PSK authentication never leaks into a selected challenge.
4040

@@ -49,3 +49,5 @@ The clean installed-consumer run retained an unrelated host-clock rollback failu
4949
All eight design doubts are cleared by the named installed witnesses, policy/retirement regressions, owner/sanitizer receipts and dependency audits. No post-handshake client auth or PSK-on-H2/H3/QUIC capability is claimed. Public H2/H3 and benchmark tasks195..199, independent timer teardown200 and aggregate185 gates retain their owners. TASK-200's race was neither encountered nor edited. BSD/macOS/Windows and nonlocal backends remain unexecuted locally and are CI/v3-PR owned under AGENTS.md. No validation-loop, merge, cleanup, push, tag, publication or deployment was performed.
5050

5151
Reusable project notes: bootstrap then VPATH configure with Clang18/C++20, explicit provider flags only for TLS-on; build src before bounded Automake selection and set TESTS/check_PROGRAMS/noinst_PROGRAMS together. Stage src plus root install-pkgconfigDATA into an external prefix. Static TSan strong allocator overrides can use the standard shared runtime per executable without losing fault probes. Real443 requires the disposable loopback-enabled namespace route here. Mature registry retirement must destroy user captures outside writer locks.
52+
53+
Validation repair iteration 1 reproduced rejected candidate callable destruction under the registry writer lock: the bounded public regression aborts after five seconds (`rejected-retirement-red.log`). The locked helper now borrows an outer shared owner; replace, ACME publish and ACME removal retain candidate and retired snapshot ownership until after the writer guard is released, including rejection and exception exits. The public regression verifies typed invalid_argument, completed reentrant destructor, preserved listener policy and subsequent writer progress (6 tests/78 checks), while retaining the successful-retirement regression. Normal/ASan/TSan owner lanes pass. `same-host-rotation-red.log` records the previous installed consumer rejecting the missing same-host command before the new witness was implemented. Original receipts/evidence are preserved under `build/task194/repair-original`. ASan owner and TLS-off installed ptrace failures are retained; exact owner artifacts replay outside the sandbox with detect_leaks=1 and unchanged diagnostics. Refreshed strict current TLS-on/off audits retain identical public declarations; nonlocal checks remain CI/v3-PR owned.

0 commit comments

Comments
 (0)