~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-webrtc

WebRTC transport for atlibs: com.fedfork.exec.webrtc.connect in the browser, and webrtc-peer, its guest side

0
0
main
73 lines · 3.3 KB Raw History
// node --test js/ssh-datachannel.test.mjs
// connectSsh's wiring with a fake @microsoft/dev-tunnels-ssh (no npm deps): sshd's banner that
// arrived before ssh took the channel is fed first, later channel bytes follow, exec output is
// collected, and the host key fingerprint is OpenSSH's SHA256:<base64>. The real library ran
// against OpenSSH (local sshd, and live on a guest VM).
import assert from "node:assert/strict";
import { Buffer } from "node:buffer";
import { createHash } from "node:crypto";
import { test } from "node:test";

import { connectSsh } from "./ssh-datachannel.js";

const HOST_KEY = Buffer.from("host-key-blob");

function fakeSsh(seen) {
	class BaseStream {
		chunks = [];
		onData(data) { this.chunks.push(data.toString()) }
		onEnd() {}
	}
	class CommandRequestMessage {}
	class SshClientSession {
		#handler;
		onAuthenticating(handler) { this.#handler = handler }
		async connect(stream) { this.stream = seen.stream = stream; await stream.write(Buffer.from("SSH-2.0-client\r\n")) }
		async authenticateServer() {
			seen.atServerAuth = this.stream.chunks.join("");
			const e = { publicKey: { keyAlgorithmName: "ssh-rsa", getPublicKeyBytes: async () => HOST_KEY } };
			this.#handler(e);
			return !!(await e.authenticationPromise);
		}
		async authenticateClient(credentials) { seen.credentials = credentials; return true }
		async openChannel() {
			let onData, onClosed;
			return {
				onDataReceived: (f) => (onData = f),
				onClosed: (f) => (onClosed = f),
				adjustWindow: (n) => (seen.window = (seen.window ?? 0) + n),
				send: async (data) => (seen.stdin ??= []).push(data.toString()),
				request: async (req) => {
					seen.request = { ...req };
					queueMicrotask(() => { onData(Buffer.from(`ran ${req.command}\n`)); onClosed() });
					return true;
				},
			};
		}
		close() { seen.closed = true }
	}
	return { BaseStream, CommandRequestMessage, SshClientSession, SshSessionConfiguration: class {}, Buffer };
}

test("connectSsh: banner first, then the channel; exec as user with the key; OpenSSH host key fingerprint", async () => {
	const seen = {};
	const sent = [];
	const dc = { send: (d) => sent.push(Buffer.from(d).toString()), close() {} };
	const banner = new TextEncoder().encode("SSH-2.0-OpenSSH_9.6\r\n").buffer;
	const session = await connectSsh(fakeSsh(seen), dc, { key: "pair" }, "root", [banner]);
	assert.equal(seen.atServerAuth, "SSH-2.0-OpenSSH_9.6\r\n");
	assert.deepEqual(sent, ["SSH-2.0-client\r\n"]);
	assert.deepEqual(seen.credentials, { username: "root", publicKeys: [{ key: "pair" }] });
	assert.deepEqual(session.hostKey, { type: "ssh-rsa", fingerprint: `SHA256:${createHash("sha256").update(HOST_KEY).digest("base64").replace(/=+$/, "")}` });
	dc.onmessage({ data: new TextEncoder().encode("more").buffer });
	assert.equal(seen.stream.chunks.join(""), "SSH-2.0-OpenSSH_9.6\r\nmore");
	assert.equal(await session.exec("id"), "ran id\n");
	assert.deepEqual(seen.request, { requestType: "exec", command: "id", wantReply: true });
	assert.equal(seen.window, "ran id\n".length);
	assert.equal(seen.stdin, undefined, "no stdin, no EOF: as before");
	// a secret goes to the command's stdin (then EOF), not into the exec request's command
	assert.equal(await session.exec("IFS= read -r t", "tok\n"), "ran IFS= read -r t\n");
	assert.deepEqual(seen.stdin, ["tok\n", ""]);
	session.close();
	assert.ok(seen.closed);
});