feat: downstream host key pinning (#1)
This commit is contained in:
@@ -23,7 +23,7 @@ function counter(onBytes) {
|
||||
// Connect the upstream ssh2.Client, retrying once after a short pause if the
|
||||
// first attempt fails auth (SSSD/AuthorizedKeysCommand cache lag right after a
|
||||
// first-time key injection).
|
||||
function connectUpstream({ host, port, username, privateKey, cert, onHostKey, uid, justInjected }) {
|
||||
function connectUpstream({ host, port, username, privateKey, cert, onHostKey, uid, justInjected, expectedHostKeyFp }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let attempted = false;
|
||||
const dial = (allowRetry) => {
|
||||
@@ -48,7 +48,10 @@ function connectUpstream({ host, port, username, privateKey, cert, onHostKey, ui
|
||||
hostVerifier: (key) => {
|
||||
const fp = 'SHA256:' + crypto.createHash('sha256').update(key).digest('base64').replace(/=+$/, '');
|
||||
if (onHostKey) onHostKey(fp);
|
||||
return true; // v1: trust-on-use, fingerprint audited. Pinning = follow-up.
|
||||
if (expectedHostKeyFp && expectedHostKeyFp !== fp) {
|
||||
return false;
|
||||
}
|
||||
return true; // v1: trust-on-use if not pinned, fingerprint audited.
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -150,6 +150,7 @@ async function resolveAndConnect(state, record, { onHostKey } = {}) {
|
||||
host: endpoint.address, port: endpoint.port,
|
||||
username: state.uid, privateKey: JUMP_KEYS.clientKey, cert,
|
||||
uid: state.uid, justInjected, onHostKey,
|
||||
expectedHostKeyFp: host && host.metadata && host.metadata.sshHostKeyFp,
|
||||
});
|
||||
} catch (err) { throw fail('upstream-unreachable', err.message, host ? host.slug : undefined); }
|
||||
|
||||
@@ -261,6 +262,7 @@ async function runTuiSession(session, client, state) {
|
||||
host: endpoint.address, port: endpoint.port,
|
||||
username: state.uid, privateKey: JUMP_KEYS.clientKey, cert,
|
||||
uid: state.uid, justInjected, onHostKey: (fp) => record.patch({ hostKeyFp: fp }),
|
||||
expectedHostKeyFp: tui.host && tui.host.metadata && tui.host.metadata.sshHostKeyFp,
|
||||
});
|
||||
} catch (err) {
|
||||
try { tui.channel.write(`\r\n Could not reach ${endpoint.address}.\r\n`); tui.channel.close(); } catch (_) {}
|
||||
|
||||
Reference in New Issue
Block a user