Release v2.19.0
- Protocol version 2.19.0 (SCRAM-SHA-256 daemon auth replacing the replayable digest) - Salted PBKDF2 verifier store + --hash-credentials; legacy store hard-rejected - Persistent anti-enumeration dummy key (<store>.dummykey) - Verified TLS / opted-in loopback transport required for auth modules - Secret wiping; carried-over hardening from the security phases - Add CHANGELOG.md and set the CMake project version
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to FastSync are documented here. Versions match
|
||||||
|
`PROTOCOL_VERSION` (printed by `fastsync --version`); the client and server must
|
||||||
|
run the same version because the handshake is strict.
|
||||||
|
|
||||||
|
## [2.19.0] - 2026-09-12
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- **Daemon authentication rewritten as SCRAM-SHA-256 challenge/response**
|
||||||
|
(`STATUS_AUTH_CHALLENGE` → `STATUS_AUTH_RESPONSE` → `STATUS_AUTH_OK`/`STATUS_AUTH_FAILED`),
|
||||||
|
replacing the old replayable static `SHA-256(password)` bearer credential.
|
||||||
|
Each proof is bound to a fresh per-connection server nonce plus a client
|
||||||
|
nonce, so a captured response can never be reused.
|
||||||
|
- **Salted verifier store.** `--password-file`/`--early-input` now hold
|
||||||
|
`user:$fastsync$1$pbkdf2-sha256$<iters>$<salt>$<stored_key>$<server_key>`
|
||||||
|
(PBKDF2-HMAC-SHA256, default 600000 iterations, range 100000–10000000). The
|
||||||
|
legacy `user:SHA256HEX` form is hard-rejected; there is no auto-upgrade.
|
||||||
|
Generate stores offline with `fastsync-server --hash-credentials FILE
|
||||||
|
[--iterations N]`.
|
||||||
|
- **Username-enumeration hardening.** Unknown/off-list users are answered with a
|
||||||
|
dummy verifier whose salt is a deterministic per-username value
|
||||||
|
(`HMAC-SHA256(dummy_key, username)`), using the store-wide uniform iteration
|
||||||
|
count and a constant-time full-length membership scan. The dummy key is
|
||||||
|
persisted in an owner-only `<store>.dummykey` sidecar (atomic publish, exact
|
||||||
|
mode 0600) so challenges are stable across restarts.
|
||||||
|
- **Verified transport for auth-required modules.** A module with `auth users`
|
||||||
|
accepts credentials only over verified TLS whose client certificate matches
|
||||||
|
`--client-cn`, or — when `--allow-unauthenticated` is explicitly set —
|
||||||
|
plaintext from a loopback peer. Remote plaintext is refused before any
|
||||||
|
challenge. Clients must use `--tls` to send `--password-file` credentials to a
|
||||||
|
non-loopback daemon; `--client-cn` is mandatory with `--tls`.
|
||||||
|
- **Secret hygiene.** The plaintext password, derived keys, nonces/proofs and
|
||||||
|
the dummy key are wiped from memory on every path and never logged.
|
||||||
|
- Carried-over hardening: `-K` TOCTOU-safe directory walk
|
||||||
|
(`openat(O_NOFOLLOW)` per component), always shell-quoted SSH remote path,
|
||||||
|
TLS compression/renegotiation disabled, race-free (open-then-`fstat`)
|
||||||
|
`--password-file`/`--early-input` checks, log-injection escaping, and lazy
|
||||||
|
protocol debug escaping.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `fastsync-server --hash-credentials FILE [--iterations N]` offline tool.
|
||||||
|
- `<store>.dummykey` sidecar (auto-created, owner-only, 0600).
|
||||||
|
- Integration tests for auth replay rejection, malformed frames, legacy-store
|
||||||
|
refusal, and the loopback/TLS transport policy; fuzz targets for config
|
||||||
|
receive and daemon-auth parsing.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Protocol version 2.18.0 → 2.19.0 (breaking).** The config-frame auth block
|
||||||
|
is now `[present][username]` (digest removed) and the auth challenge/response
|
||||||
|
frames are interleaved between the config frame and its `STATUS_OK`. A 2.19.0
|
||||||
|
client and a 2.18.0 server (or vice versa) fail cleanly at the handshake.
|
||||||
|
- Daemon modules declaring `auth users` require a configured credential store at
|
||||||
|
startup (fail closed); operators regenerate stores from plaintext with
|
||||||
|
`--hash-credentials`.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- First tagged release. FastSync implements rsync-compatible file
|
||||||
|
synchronization over TCP and SSH with TLS (OpenSSL), streaming zstd
|
||||||
|
compression, multithreaded transfers, and incremental sync. See
|
||||||
|
[RSYNC_COMPAT.md](RSYNC_COMPAT.md) for the flag-parity matrix.
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
|
|
||||||
project(FastFileTransfer)
|
project(FastFileTransfer VERSION 2.19.0)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ source/destination model and rsync-style options while adding optional
|
|||||||
multithreading, streaming zstd compression, chunking, zero-copy TCP transfers,
|
multithreading, streaming zstd compression, chunking, zero-copy TCP transfers,
|
||||||
and native TCP/TLS transports.
|
and native TCP/TLS transports.
|
||||||
|
|
||||||
|
The release version is FastSync's client/server protocol version (printed by
|
||||||
|
`fastsync --version`); client and server must match. See
|
||||||
|
[CHANGELOG.md](CHANGELOG.md) for the history.
|
||||||
|
|
||||||
The compatibility target is straightforward:
|
The compatibility target is straightforward:
|
||||||
|
|
||||||
- Existing rsync commands should keep the same meaning.
|
- Existing rsync commands should keep the same meaning.
|
||||||
|
|||||||
Reference in New Issue
Block a user