fix(review): close loopback TLS auth bypass; align docs and wrong-CN test

- server gate: the --allow-unauthenticated loopback allowance now requires
  an actual plaintext connection (!gate_ctx->ssl), so a loopback TLS client
  whose cert fails the --client-cn check is refused before any SCRAM
  challenge instead of falling through the plaintext opt-in.  Keep the
  invalid-fd guard as belt-and-braces (unreachable after the policy check).
- test: rewrote test_wrong_client_cn_refused_before_auth_challenge to run
  deterministically over 127.0.0.1 with --tls + --allow-unauthenticated and
  a CA-valid wrong-CN client cert, asserting the gate refusal log and an
  unchanged module tree (no skip).
- docs: --client-cn is mandatory with --tls; dummykey sidecar is secret
  material; document all transient-fallback reasons; qualify
  --allow-unauthenticated in README and --help so it cannot read as
  permitting remote plaintext auth.
- credentials.h: drop stale restrictive-umask claim (fchmod forces exact
  0600; only create/write/fsync/link/fchmod failure degrades to ephemeral).
This commit is contained in:
2026-09-12 19:50:52 +02:00
parent 89b967f29a
commit 1b90ee2449
5 changed files with 49 additions and 40 deletions
+5 -4
View File
@@ -32,10 +32,11 @@
* the dummy challenge for an unknown user stable for the life of the store, so
* a daemon restart cannot be used as a username-enumeration oracle. A sidecar
* that is not an exact-mode-0600 regular file of exactly 32 bytes fails the load
* (fail closed); if it cannot be created (e.g. a read-only mount or a restrictive
* umask the fchmod cannot repair) the daemon warns and uses a transient per-run
* key instead. NOTE: the sidecar requires EXACT 0600, whereas the store /
* password files only reject group/other bits (a deliberate difference).
* (fail closed); creation forces exact 0600 with fchmod (so a restrictive umask
* cannot leave the sidecar unreadable), and only a create/write/fsync/link or
* fchmod failure degrades to a transient per-run key with a warning. NOTE: the
* sidecar requires EXACT 0600, whereas the store / password files only reject
* group/other bits (a deliberate difference).
*
* Client --password-file format: the FIRST meaningful (non-comment, non-blank)
* line is `user:password`, holding the literal password. The client keeps it