Skip to content

Align with LocalSend 1.18: present the client certificate, protocol 2.2 - #1

Open
AlexDevFlow wants to merge 1 commit into
mainfrom
align-localsend-1.18
Open

Align with LocalSend 1.18: present the client certificate, protocol 2.2#1
AlexDevFlow wants to merge 1 commit into
mainfrom
align-localsend-1.18

Conversation

@AlexDevFlow

Copy link
Copy Markdown
Owner

Why

LocalSend 1.18 requires a client certificate on its HTTPS server whenever it is not serving its web pages — which is the normal receive state. lsq built its discovery HTTP client without an identity, so its reply to an announcement died in the handshake:

caused by: received fatal alert: CertificateRequired

The peer therefore never learned lsq existed, except by chance from lsq's own next announcement.

What changed

  • Present the certificate on every outgoing HTTPS request, as the official client does: discovery::discover, announce_presence, and pull_files now take the identity instead of using a certless client.
  • Protocol 2.1 → 2.2, and a checksum mismatch now answers 422 rather than 500. That status is the only thing 2.2 adds, and it matches the official server.
  • tests/mtls.rs: a self-contained regression guard that stands up a server demanding a client certificate, asserting the certless client is refused and the identity client gets through. No LocalSend checkout needed.

On protocol v3

Deliberately not implemented — it is scaffolding, not a live protocol:

  • The spec repo carries only two sequence diagrams under v3/; its README is still v2.2 and the CHANGELOG stops at 2.2.
  • v1.18.2 routes just /v3/nonce and /v3/register. There is no v3 prepare-upload, upload, cancel or pair, and v3::register is a stub marked // TODO: not wired up yet.
  • The app pins its own client to LsHttpClientVersion.v2 at both construction sites; "3.0" appears nowhere in the repo, and devices announce 2.2.

Worth revisiting when the app starts using it.

Verification

Checked against the real LocalSend 1.18.2 core (packages/core) in both directions:

Scenario Result
lsq → real receiver, normal receive mode file arrives byte-identical
real client → lsq receive file arrives byte-identical
lsq register, incl. the new fingerprint/cert cross-check accepted, event emitted
certless client vs mTLS peer CertificateRequired (the bug)
identity client vs mTLS peer 200 OK (the fix)

Plus the full lsq suite and cargo clippy --all-targets -- -D warnings.

Three tests (session_is_bound_to_ip, cancel_from_other_ip_is_ignored, upload_from_different_ip_is_403) fail on macOS both before and after this change: they bind a 127.0.0.2 source address, which Linux aliases automatically and macOS does not. They pass in CI. Left alone here.

🤖 Generated with Claude Code

LocalSend 1.18 requires a client certificate on its HTTPS server whenever it
is not serving its web pages, which is the normal receive state. lsq built its
discovery HTTP client without an identity, so its reply to an announcement died
in the handshake with a CertificateRequired alert and the peer never learned
lsq existed. Discovery, presence announcements and pull now all present the
certificate, the way the official client does on every request.

Bump the protocol to 2.2 and answer a checksum mismatch with 422 instead of
500: that status is the one thing 2.2 adds, and it is what the official server
returns.

Protocol v3 is deliberately not implemented. 1.18.2 routes only /v3/nonce and
/v3/register, its v3 register handler is a stub marked "not wired up yet", and
the app pins its own HTTP client to v2. Devices still announce 2.2 and still
transfer over the v2 endpoints, so there is nothing live to talk to on v3.

Checked against the LocalSend 1.18.2 core in both directions, with the files
arriving byte-identical. tests/mtls.rs is a self-contained regression guard:
it stands up a server that demands a client certificate and asserts that a
certless client is refused and lsq's identity client gets through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant