mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-30 23:25:24 +00:00
fix: host key silently accepted when the host is missing from the database (#1397)
This commit is contained in:
1 parent
44be18988b
commit
b3e220acf1
2 files changed
+75
-2
No files matched your search
@@ -84,18 +84,47 @@ export class SSHHostKeyVerifier {
|
|||||||
hostId,
|
hostId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// No row means nothing to compare against and nowhere to save the
|
||||||
|
// key, so it is never accepted silently (#1397): the user decides
|
||||||
|
// when there is a socket to ask on, otherwise it is refused.
|
||||||
if (!host) {
|
if (!host) {
|
||||||
|
if (!ws) {
|
||||||
|
sshLogger.error(
|
||||||
|
"Host not found in database during key verification, rejecting",
|
||||||
|
{
|
||||||
|
operation: "host_key_no_host",
|
||||||
|
hostId,
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
verify(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const accepted = await this.promptUserForNewKey(
|
||||||
|
ws,
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
undefined,
|
||||||
|
fingerprint,
|
||||||
|
keyType,
|
||||||
|
algorithm,
|
||||||
|
);
|
||||||
sshLogger.warn(
|
sshLogger.warn(
|
||||||
"Host not found in database during key verification",
|
accepted
|
||||||
|
? "Key for a host missing from the database accepted for this session only"
|
||||||
|
: "Key for a host missing from the database rejected",
|
||||||
{
|
{
|
||||||
operation: "host_key_no_host",
|
operation: "host_key_no_host",
|
||||||
hostId,
|
hostId,
|
||||||
ip,
|
ip,
|
||||||
port,
|
port,
|
||||||
|
fingerprint,
|
||||||
userId,
|
userId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
verify(true);
|
verify(accepted);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,3 +76,47 @@ describe("host key recovery", () => {
|
|||||||
expect(accepted).toEqual([]);
|
expect(accepted).toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("a host missing from the database", () => {
|
||||||
|
function answeringSocket(action: "accept" | "reject") {
|
||||||
|
const socket = new EventEmitter() as EventEmitter & {
|
||||||
|
send: (data: string) => void;
|
||||||
|
};
|
||||||
|
socket.send = () =>
|
||||||
|
socket.emit(
|
||||||
|
"message",
|
||||||
|
Buffer.from(
|
||||||
|
JSON.stringify({
|
||||||
|
type: "host_key_verification_response",
|
||||||
|
data: { action },
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return socket as unknown as WebSocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyMissingHost(ws: WebSocket | null) {
|
||||||
|
const verifier = await SSHHostKeyVerifier.createHostVerifier(
|
||||||
|
hostId,
|
||||||
|
"127.0.0.1",
|
||||||
|
22,
|
||||||
|
ws,
|
||||||
|
"user",
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
return new Promise<boolean>((resolve) =>
|
||||||
|
verifier(Buffer.from("any-key"), resolve),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
it("refuses the key when nobody can be asked", async () => {
|
||||||
|
expect(await verifyMissingHost(null)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("asks the user and saves nothing", async () => {
|
||||||
|
expect(await verifyMissingHost(answeringSocket("accept"))).toBe(true);
|
||||||
|
expect(await verifyMissingHost(answeringSocket("reject"))).toBe(false);
|
||||||
|
expect(updateHostKey).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user