fix(d5-daemon-auth): address auth review findings (Wave B)

- test_credentials.c: NUL-terminate the overlong-line stack buffer before
  make_tmp_file's strlen() (was a stack-buffer-overflow READ under ASan);
  still exercises the overlong-rejection path.
- Add redacted protocol string variants (protocol_send_str_redacted /
  receive + fd send_str_redacted/receive_str_redacted) and use them for the
  daemon auth username/digest so --verbose / LOG_DEBUG_ALL never logs a
  replayable credential while other protocol strings keep their debug trace.
- credentials_verify/gate: replace byte-wise-short-circuiting strcmp with a
  fixed-length constant-time username compare (closes user-enumeration oracle);
  update doc comment to match.
- read_secret_file: preserve password exact bytes (only strip trailing CR/LF)
  and burn the stack line buffer; document the whitespace behavior.
- test_server_cli.c: note the parser zero-inits opts on failure.
- Add debug-level daemon test asserting the digest never appears under --verbose.

PROTOCOL_VERSION stays 2.15.0.
This commit is contained in:
2026-09-10 13:20:42 +02:00
parent dd5ae60459
commit accd34ad60
8 changed files with 155 additions and 18 deletions
+7 -3
View File
@@ -1110,7 +1110,10 @@ static bool send_daemon_auth(int fd, const Config* c) {
return false;
if (!present)
return true;
return send_str(fd, c->auth_user) && send_str(fd, c->auth_password_hash);
/* Redacted send: the username and hard-wired digest must never reach a
* --verbose debug log (they are replayable), while normal protocol strings
* keep their debug trace. */
return send_str_redacted(fd, c->auth_user) && send_str_redacted(fd, c->auth_password_hash);
}
static bool receive_daemon_auth(int fd, Config* c) {
@@ -1119,8 +1122,9 @@ static bool receive_daemon_auth(int fd, Config* c) {
return false;
if (!present)
return true;
char* user = receive_str(fd);
char* hash = receive_str(fd);
/* Redacted receive: never log the incoming username/digest bodies. */
char* user = receive_str_redacted(fd);
char* hash = receive_str_redacted(fd);
if (!user || !hash) {
free(user);
free(hash);