mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-11-02 16:45:24 +00:00
v26.11.0 (#1756)
* fix: only show connection lost when the server check fails too * fix: load the macOS tray icon from the right unpacked folder (#1728) * fix: hide update and review buttons on disabled plugins (#1745) * fix: save the database without blocking the server, bump to 26.11.0 * fix: try the key before the password for hosts with both (Plugin-SSH-Terminal#50) * fix: add macOS Window menu item to reopen main window * feat: upload Mac App Store screenshots on submit * chore: drop internal note from changelog * chore: update translations and plugin pins * chore: lint, format, and bump version to 26.11.0
This commit is contained in:
1 parent
c759a147c6
commit
1d4eac3e20
24 files changed
+337
-56
No files matched your search
@@ -0,0 +1,68 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import ssh2 from "ssh2";
|
||||
|
||||
const { Client, Server, utils } = ssh2;
|
||||
|
||||
// The order prepareKey sets when a host has both a key and a password.
|
||||
const AUTH_ORDER = ["publickey", "password", "keyboard-interactive"];
|
||||
const keys = utils.generateKeyPairSync("ed25519");
|
||||
|
||||
let server: InstanceType<typeof Server> | null = null;
|
||||
afterEach(() => server?.close());
|
||||
|
||||
/** A server with AuthenticationMethods publickey,password. */
|
||||
function start(): Promise<number> {
|
||||
server = new Server({ hostKeys: [keys.private] }, (client) => {
|
||||
let keyDone = false;
|
||||
client.on("authentication", (ctx) => {
|
||||
if (ctx.method === "publickey") {
|
||||
if (ctx.signature) {
|
||||
keyDone = true;
|
||||
ctx.reject(["password"], true);
|
||||
} else {
|
||||
ctx.accept();
|
||||
}
|
||||
} else if (ctx.method === "password" && keyDone) {
|
||||
ctx.accept();
|
||||
} else {
|
||||
ctx.reject(keyDone ? ["password"] : ["publickey"]);
|
||||
}
|
||||
});
|
||||
client.on("ready", () => client.end());
|
||||
client.on("error", () => {});
|
||||
});
|
||||
return new Promise((resolve) => {
|
||||
server!.listen(0, "127.0.0.1", () =>
|
||||
resolve((server!.address() as { port: number }).port),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function connect(port: number, authHandler?: string[]) {
|
||||
return new Promise<string>((resolve) => {
|
||||
const client = new Client();
|
||||
client.on("ready", () => {
|
||||
client.end();
|
||||
resolve("ready");
|
||||
});
|
||||
client.on("error", (error) => resolve(error.message));
|
||||
client.connect({
|
||||
host: "127.0.0.1",
|
||||
port,
|
||||
username: "u",
|
||||
privateKey: keys.private,
|
||||
password: "pw",
|
||||
...(authHandler ? { authHandler } : {}),
|
||||
} as never);
|
||||
});
|
||||
}
|
||||
|
||||
describe("a server that wants a key, then a password", () => {
|
||||
it("logs in with the key first order", async () => {
|
||||
expect(await connect(await start(), AUTH_ORDER)).toBe("ready");
|
||||
});
|
||||
|
||||
it("fails with ssh2's default order, which tries the password first", async () => {
|
||||
expect(await connect(await start())).toMatch(/authentication/i);
|
||||
});
|
||||
});
|
||||
@@ -205,6 +205,11 @@ describe("buildConnectConfig per auth type", () => {
|
||||
expect(Buffer.isBuffer(config.privateKey)).toBe(true);
|
||||
expect(config.passphrase).toBe("secret");
|
||||
expect(config.password).toBe("fallback");
|
||||
expect(config.authHandler).toEqual([
|
||||
"publickey",
|
||||
"password",
|
||||
"keyboard-interactive",
|
||||
]);
|
||||
expect(mocks.applyCertificateAuth).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user