Implement password handling for unattended access
build / build-linux-amd64 (push) Successful in 2m0s
build / build-linux-amd64 (push) Successful in 2m0s
This commit is contained in:
Vendored
+6
-6
File diff suppressed because one or more lines are too long
Vendored
+3
-3
File diff suppressed because one or more lines are too long
@@ -166,11 +166,22 @@ export class Session {
|
||||
// UTF-8 bytes the way the Rust side reads them.
|
||||
// pwd_hash = SHA256(password_text || salt_utf8_bytes)
|
||||
// password_response = SHA256(pwd_hash || challenge_utf8_bytes)
|
||||
//
|
||||
// Special case the empty password: the desktop client sends LITERAL
|
||||
// empty bytes for `lr.password` when the user hasn't typed a
|
||||
// password yet (client.rs:3472-3475 — "login without password, the
|
||||
// remote side can click accept"). The host's connection.rs:2488
|
||||
// branches on `lr.password.is_empty()` to start the cm_popup
|
||||
// approval flow; if we send a SHA-256-derived 32-byte response
|
||||
// instead, the host treats it as a wrong-password attempt and
|
||||
// returns LOGIN_MSG_PASSWORD_WRONG, which collapses the
|
||||
// attended-no-password approval path.
|
||||
const enc = new TextEncoder();
|
||||
const saltBytes = enc.encode(salt);
|
||||
const challengeBytes = enc.encode(challenge);
|
||||
const pwdHash = sha256(concat(opts.password, saltBytes));
|
||||
const passwordResp = sha256(concat(pwdHash, challengeBytes));
|
||||
const passwordResp = opts.password.length === 0
|
||||
? new Uint8Array(0)
|
||||
: sha256(concat(sha256(concat(opts.password, saltBytes)), challengeBytes));
|
||||
|
||||
// -------- 8. Send Message{login_request} --------
|
||||
const loginReq = hbb.Message.create({
|
||||
@@ -219,6 +230,19 @@ export class Session {
|
||||
// replay them into its main receive dispatch.
|
||||
const preloginExtras: hbb.Message[] = [];
|
||||
let approvalNotified = false;
|
||||
// Empty-password path: when the host has a permanent password set
|
||||
// AND a user is logged in, connection.rs:2488 just calls
|
||||
// try_start_cm and stays silent (no LOGIN_MSG_NO_PASSWORD_ACCESS).
|
||||
// The desktop client renders "Please wait for the remote side…" on
|
||||
// its own as soon as it sends LoginRequest in that case; we do the
|
||||
// same here so the UI doesn't sit on the "secure handshake + login"
|
||||
// step indefinitely. The notification is idempotent — if the host
|
||||
// *does* later send LOGIN_MSG_NO_PASSWORD_ACCESS, the existing
|
||||
// branch below no-ops on `approvalNotified`.
|
||||
if (passwordResp.length === 0) {
|
||||
approvalNotified = true;
|
||||
try { opts.onAwaitingApproval?.(); } catch { /* swallow */ }
|
||||
}
|
||||
while (true) {
|
||||
const respMsg = await session.recv();
|
||||
if (respMsg.test_delay) {
|
||||
|
||||
Reference in New Issue
Block a user