From 6b0b1563c56cd23ff2327e9a99bc3438e1859796 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sat, 28 Dec 2024 14:12:55 +0100 Subject: [PATCH] bump russh --- app/package.json | 2 +- app/yarn.lock | 11 +++++---- tabby-ssh/src/session/ssh.ts | 45 ++++++++++++++++++++++++++---------- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/app/package.json b/app/package.json index 69699bcf..ca520469 100644 --- a/app/package.json +++ b/app/package.json @@ -30,7 +30,7 @@ "native-process-working-directory": "^1.0.2", "npm": "6", "rxjs": "^7.5.7", - "russh": "0.0.4", + "russh": "0.1.2", "source-map-support": "^0.5.20", "v8-compile-cache": "^2.3.0", "yargs": "^17.7.2" diff --git a/app/yarn.lock b/app/yarn.lock index 9c73826a..4a11728e 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -3636,10 +3636,10 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -russh@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/russh/-/russh-0.0.4.tgz#eb3f7d16db30bfd79f08afb6c5073ff097ff0f47" - integrity sha512-Giomd+JrFcwmcwGcaKEFTJHkSV0/aBpYxjtZp7/AsffOy7GW40NizprpeQyTdLI7e0shOtjOTMXBJUZqRuGSzg== +russh@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/russh/-/russh-0.1.2.tgz#c32e2e6e1057ceb1a6bdbac05ed9edc4eb4416ab" + integrity sha512-1AotR7mM1lA1zK7vbkHo6YJazz5jy6mdrlxLxIWRQE4BLAqrW+6L3PCy1lA48A6Y4KP2TUMCIKNNmSpsgPd1Yg== dependencies: "@napi-rs/cli" "^2.18.3" @@ -3950,6 +3950,7 @@ strict-uri-encode@^2.0.0: integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + name string-width-cjs version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4027,6 +4028,7 @@ stringify-package@^1.0.0, stringify-package@^1.0.1: integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: + name strip-ansi-cjs version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4473,6 +4475,7 @@ worker-farm@^1.6.0, worker-farm@^1.7.0: errno "~0.1.7" "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== diff --git a/tabby-ssh/src/session/ssh.ts b/tabby-ssh/src/session/ssh.ts index 8444795e..46fe01c5 100644 --- a/tabby-ssh/src/session/ssh.ts +++ b/tabby-ssh/src/session/ssh.ts @@ -37,6 +37,7 @@ type AuthMethod = { type: 'publickey' name: string contents: Buffer + hashAlg: 'sha256'|'sha512'|'sha1'|null } | { type: 'agent', kind: 'unix-socket', @@ -137,29 +138,37 @@ export class SSHSession { }) } + private addPublicKeyAuthMethod (name: string, contents: Buffer) { + for (const hashAlg of ['sha512', 'sha256', 'sha1', null] as const) { + this.remainingAuthMethods.push({ + type: 'publickey', + name, + contents, + hashAlg, + }) + } + } + async init (): Promise { this.remainingAuthMethods = [{ type: 'none' }] if (!this.profile.options.auth || this.profile.options.auth === 'publicKey') { if (this.profile.options.privateKeys?.length) { for (const pk of this.profile.options.privateKeys) { + // eslint-disable-next-line @typescript-eslint/init-declarations + let contents: Buffer try { - this.remainingAuthMethods.push({ - type: 'publickey', - name: pk, - contents: await this.fileProviders.retrieveFile(pk), - }) + contents = await this.fileProviders.retrieveFile(pk) } catch (error) { this.emitServiceMessage(colors.bgYellow.yellow.black(' ! ') + ` Could not load private key ${pk}: ${error}`) + continue } + + this.addPublicKeyAuthMethod(pk, contents) } } else { for (const importer of this.privateKeyImporters) { for (const [name, contents] of await importer.getKeys()) { - this.remainingAuthMethods.push({ - type: 'publickey', - name, - contents, - }) + this.addPublicKeyAuthMethod(name, contents) } } } @@ -523,7 +532,17 @@ export class SSHSession { if (method.type === 'publickey') { try { const key = await this.loadPrivateKey(method.name, method.contents) - const result = await this.ssh.authenticateWithKeyPair(this.authUsername, key) + const possibleHashAlgs = (['ssh-rsa', 'rsa-sha2-256', 'rsa-sha2-512'].includes(key.algorithm) ? ['sha256', 'sha512', 'sha1'] : [null]) as (string|null)[] + if (!possibleHashAlgs.includes(method.hashAlg)) { + // skip incompatible hash algs + continue + } + let msg = `Using private key: ${method.name}` + if (method.hashAlg) { + msg += ` (${method.hashAlg})` + } + this.emitServiceMessage(msg) + const result = await this.ssh.authenticateWithKeyPair(this.authUsername, key, method.hashAlg) if (result) { return result } @@ -692,13 +711,15 @@ export class SSHSession { } async loadPrivateKey (name: string, privateKeyContents: Buffer): Promise { - this.emitServiceMessage(`Loading private key: ${name}`) this.activePrivateKey = await this.loadPrivateKeyWithPassphraseMaybe(privateKeyContents.toString()) return this.activePrivateKey } async loadPrivateKeyWithPassphraseMaybe (privateKey: string): Promise { const keyHash = crypto.createHash('sha512').update(privateKey).digest('hex') + + privateKey = privateKey.replaceAll('EC PRIVATE KEY', 'PRIVATE KEY') + let triedSavedPassphrase = false let passphrase: string|null = null while (true) {