mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-04 18:39:54 +00:00
updated ssh2
This commit is contained in:
parent
d435abd944
commit
779eb235f3
@ -38,6 +38,7 @@
|
|||||||
"npm": "6",
|
"npm": "6",
|
||||||
"path": "0.12.7",
|
"path": "0.12.7",
|
||||||
"rxjs": "^7.1.0",
|
"rxjs": "^7.1.0",
|
||||||
|
"ssh2": "^1.1.0",
|
||||||
"yargs": "^17.0.1",
|
"yargs": "^17.0.1",
|
||||||
"zone.js": "^0.11.4"
|
"zone.js": "^0.11.4"
|
||||||
},
|
},
|
||||||
|
@ -73,10 +73,7 @@ const builtinModules = [
|
|||||||
|
|
||||||
const cachedBuiltinModules = {}
|
const cachedBuiltinModules = {}
|
||||||
builtinModules.forEach(m => {
|
builtinModules.forEach(m => {
|
||||||
const label = 'Caching ' + m
|
|
||||||
console.time(label)
|
|
||||||
cachedBuiltinModules[m] = nodeRequire(m)
|
cachedBuiltinModules[m] = nodeRequire(m)
|
||||||
console.timeEnd(label)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const originalRequire = (global as any).require
|
const originalRequire = (global as any).require
|
||||||
@ -183,14 +180,11 @@ export async function loadPlugins (foundPlugins: PluginInfo[], progress: Progres
|
|||||||
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
||||||
progress(index, foundPlugins.length)
|
progress(index, foundPlugins.length)
|
||||||
try {
|
try {
|
||||||
const label = 'Loading ' + foundPlugin.name
|
|
||||||
console.time(label)
|
|
||||||
const packageModule = nodeRequire(foundPlugin.path)
|
const packageModule = nodeRequire(foundPlugin.path)
|
||||||
const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
||||||
pluginModule.pluginName = foundPlugin.name
|
pluginModule.pluginName = foundPlugin.name
|
||||||
pluginModule.bootstrap = packageModule.bootstrap
|
pluginModule.bootstrap = packageModule.bootstrap
|
||||||
plugins.push(pluginModule)
|
plugins.push(pluginModule)
|
||||||
console.timeEnd(label)
|
|
||||||
await new Promise(x => setTimeout(x, 50))
|
await new Promise(x => setTimeout(x, 50))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Could not load ${foundPlugin.name}:`, error)
|
console.error(`Could not load ${foundPlugin.name}:`, error)
|
||||||
|
@ -295,7 +295,7 @@ asap@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz"
|
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz"
|
||||||
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
||||||
|
|
||||||
asn1@~0.2.3:
|
asn1@^0.2.4, asn1@~0.2.3:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz"
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz"
|
||||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||||
@ -332,7 +332,7 @@ base64-js@^1.3.1:
|
|||||||
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
|
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
|
||||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||||
|
|
||||||
bcrypt-pbkdf@^1.0.0:
|
bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
|
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
|
||||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||||
@ -686,6 +686,13 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
|
cpu-features@0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.2.tgz#9f636156f1155fd04bdbaa028bb3c2fbef3cea7a"
|
||||||
|
integrity sha512-/2yieBqvMcRj8McNzkycjW2v3OIUOibBfd2dLEJ0nWts8NobAxwiyw9phVNS6oDL8x8tz9F7uNVFEVpJncQpeA==
|
||||||
|
dependencies:
|
||||||
|
nan "^2.14.1"
|
||||||
|
|
||||||
create-error-class@^3.0.0:
|
create-error-class@^3.0.0:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
|
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
|
||||||
@ -2081,7 +2088,7 @@ mz@^2.7.0:
|
|||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
thenify-all "^1.0.0"
|
thenify-all "^1.0.0"
|
||||||
|
|
||||||
nan@^2.13.2, nan@^2.14.0, nan@^2.14.2:
|
nan@^2.13.2, nan@^2.14.0, nan@^2.14.1, nan@^2.14.2:
|
||||||
version "2.14.2"
|
version "2.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||||
@ -3205,6 +3212,17 @@ split-on-first@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
||||||
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
||||||
|
|
||||||
|
ssh2@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.1.0.tgz#43dd24930e15e317687f519d6b40270d9cd00d00"
|
||||||
|
integrity sha512-CidQLG2ZacoT0Z7O6dOyisj4JdrOrLVJ4KbHjVNz9yI1vO08FAYQPcnkXY9BP8zeYo+J/nBgY6Gg4R7w4WFWtg==
|
||||||
|
dependencies:
|
||||||
|
asn1 "^0.2.4"
|
||||||
|
bcrypt-pbkdf "^1.0.2"
|
||||||
|
optionalDependencies:
|
||||||
|
cpu-features "0.0.2"
|
||||||
|
nan "^2.14.2"
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz"
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz"
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
"shelljs": "0.8.4",
|
"shelljs": "0.8.4",
|
||||||
"source-code-pro": "^2.38.0",
|
"source-code-pro": "^2.38.0",
|
||||||
"source-sans-pro": "3.6.0",
|
"source-sans-pro": "3.6.0",
|
||||||
"ssh2-streams": "^0.4.10",
|
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"tslib": "^2.2.0",
|
"tslib": "^2.2.0",
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/ssh2": "^0.5.35",
|
|
||||||
"ansi-colors": "^4.1.1",
|
"ansi-colors": "^4.1.1",
|
||||||
"binstring": "^0.2.1",
|
"binstring": "^0.2.1",
|
||||||
"buffer-replace": "^1.0.0",
|
"buffer-replace": "^1.0.0",
|
||||||
|
@ -2,31 +2,11 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@types/node@*":
|
|
||||||
version "14.14.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
|
||||||
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
|
||||||
|
|
||||||
"@types/node@14.14.14":
|
"@types/node@14.14.14":
|
||||||
version "14.14.14"
|
version "14.14.14"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae"
|
||||||
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==
|
||||||
|
|
||||||
"@types/ssh2-streams@*":
|
|
||||||
version "0.1.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.7.tgz#bf79349ec85a4dfb5b3fd9f4a05af729121f07e6"
|
|
||||||
integrity sha512-cQNV72C+BOG7G8WNGarTQdB2Ii37cJlWatSpx5zTYxtI2ZvUt2lbq6Nc2XZ4kbge28V7Xe5KYYr82d96/rDMnQ==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
|
|
||||||
"@types/ssh2@^0.5.35":
|
|
||||||
version "0.5.45"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.45.tgz#14e293ec2a4d4c8a5434a7989a676b87340aa870"
|
|
||||||
integrity sha512-SAQITTyO/jOoskSAw2T/9sveX4lhTzx7zdeYR0t04RMhZQrEIzvrAoCStSxYwvwZ5ofek1JWeW9x2yOK3GOUlg==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
"@types/ssh2-streams" "*"
|
|
||||||
|
|
||||||
ansi-color@^0.2.1:
|
ansi-color@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a"
|
resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a"
|
||||||
|
@ -22,12 +22,9 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "14.14.31",
|
"@types/node": "14.14.31",
|
||||||
"@types/ssh2": "^0.5.35",
|
|
||||||
"ansi-colors": "^4.1.1",
|
"ansi-colors": "^4.1.1",
|
||||||
"cli-spinner": "^0.2.10",
|
"cli-spinner": "^0.2.10",
|
||||||
"clone-deep": "^4.0.1",
|
"clone-deep": "^4.0.1",
|
||||||
"ssh2": "^0.8.9",
|
|
||||||
"ssh2-streams": "Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5",
|
|
||||||
"sshpk": "Eugeny/node-sshpk#89ed17dfae425a8b629873c8337e77d26838c04f",
|
"sshpk": "Eugeny/node-sshpk#89ed17dfae425a8b629873c8337e77d26838c04f",
|
||||||
"strip-ansi": "^7.0.0"
|
"strip-ansi": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
import colors from 'ansi-colors'
|
import colors from 'ansi-colors'
|
||||||
import stripAnsi from 'strip-ansi'
|
import stripAnsi from 'strip-ansi'
|
||||||
import socksv5 from 'socksv5'
|
import socksv5 from 'socksv5'
|
||||||
|
import { Injector } from '@angular/core'
|
||||||
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { BaseSession } from 'terminus-terminal'
|
import { BaseSession } from 'terminus-terminal'
|
||||||
import { Server, Socket, createServer, createConnection } from 'net'
|
import { Server, Socket, createServer, createConnection } from 'net'
|
||||||
import { Client, ClientChannel } from 'ssh2'
|
import { Client, ClientChannel } from 'ssh2'
|
||||||
import { Logger } from 'terminus-core'
|
import { Logger } from 'terminus-core'
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
import { ProxyCommandStream } from './services/ssh.service'
|
import { ProxyCommandStream } from './services/ssh.service'
|
||||||
|
import { PasswordStorageService } from './services/passwordStorage.service'
|
||||||
|
import { PromptModalComponent } from './components/promptModal.component'
|
||||||
|
|
||||||
export interface LoginScript {
|
export interface LoginScript {
|
||||||
expect: string
|
expect: string
|
||||||
@ -129,12 +133,22 @@ export class SSHSession extends BaseSession {
|
|||||||
logger: Logger
|
logger: Logger
|
||||||
jumpStream: any
|
jumpStream: any
|
||||||
proxyCommandStream: ProxyCommandStream|null = null
|
proxyCommandStream: ProxyCommandStream|null = null
|
||||||
|
authMethodsLeft: string[] = []
|
||||||
|
savedPassword: string|undefined
|
||||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||||
private serviceMessage = new Subject<string>()
|
private serviceMessage = new Subject<string>()
|
||||||
|
private keychainPasswordUsed = false
|
||||||
|
private passwordStorage: PasswordStorageService
|
||||||
|
private ngbModal: NgbModal
|
||||||
|
|
||||||
constructor (public connection: SSHConnection) {
|
constructor (
|
||||||
|
injector: Injector,
|
||||||
|
public connection: SSHConnection
|
||||||
|
) {
|
||||||
super()
|
super()
|
||||||
|
this.passwordStorage = injector.get(PasswordStorageService)
|
||||||
|
this.ngbModal = injector.get(NgbModal)
|
||||||
|
|
||||||
this.scripts = connection.scripts ?? []
|
this.scripts = connection.scripts ?? []
|
||||||
this.destroyed$.subscribe(() => {
|
this.destroyed$.subscribe(() => {
|
||||||
for (const port of this.forwardedPorts) {
|
for (const port of this.forwardedPorts) {
|
||||||
@ -197,7 +211,7 @@ export class SSHSession extends BaseSession {
|
|||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
this.logger.info('Executing script: "' + cmd + '"')
|
this.logger.info('Executing script: "' + cmd + '"')
|
||||||
this.shell!.write(cmd + '\n')
|
this.shell.write(cmd + '\n')
|
||||||
this.scripts = this.scripts.filter(x => x !== script)
|
this.scripts = this.scripts.filter(x => x !== script)
|
||||||
} else {
|
} else {
|
||||||
if (script.optional) {
|
if (script.optional) {
|
||||||
@ -296,6 +310,67 @@ export class SSHSession extends BaseSession {
|
|||||||
this.logger.info(stripAnsi(msg))
|
this.logger.info(stripAnsi(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleAuth (methodsLeft?: string[]): Promise<any> {
|
||||||
|
while (true) {
|
||||||
|
const method = this.authMethodsLeft.shift()
|
||||||
|
if (!method) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (methodsLeft && !methodsLeft.includes(method) && method !== 'agent') {
|
||||||
|
// Agent can still be used even if not in methodsLeft
|
||||||
|
this.logger.info('Server does not support auth method', method)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (method === 'password') {
|
||||||
|
if (this.connection.password) {
|
||||||
|
this.emitServiceMessage('Using preset password')
|
||||||
|
return {
|
||||||
|
type: 'password',
|
||||||
|
username: this.connection.user,
|
||||||
|
password: this.connection.password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.keychainPasswordUsed) {
|
||||||
|
const password = await this.passwordStorage.loadPassword(this.connection)
|
||||||
|
if (password) {
|
||||||
|
this.emitServiceMessage('Trying saved password')
|
||||||
|
this.keychainPasswordUsed = true
|
||||||
|
return {
|
||||||
|
type: 'password',
|
||||||
|
username: this.connection.user,
|
||||||
|
password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
|
modal.componentInstance.prompt = `Password for ${this.connection.user}@${this.connection.host}`
|
||||||
|
modal.componentInstance.password = true
|
||||||
|
modal.componentInstance.showRememberCheckbox = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await modal.result
|
||||||
|
if (result) {
|
||||||
|
if (result.remember) {
|
||||||
|
this.savedPassword = result.value
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: 'password',
|
||||||
|
username: this.connection.user,
|
||||||
|
password: result.value,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async addPortForward (fw: ForwardedPort): Promise<void> {
|
async addPortForward (fw: ForwardedPort): Promise<void> {
|
||||||
if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) {
|
if (fw.type === PortForwardType.Local || fw.type === PortForwardType.Dynamic) {
|
||||||
await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => {
|
await fw.startLocalListener((accept, reject, sourceAddress, sourcePort, targetAddress, targetPort) => {
|
||||||
@ -417,7 +492,7 @@ export class SSHSession extends BaseSession {
|
|||||||
for (const script of this.scripts) {
|
for (const script of this.scripts) {
|
||||||
if (!script.expect) {
|
if (!script.expect) {
|
||||||
console.log('Executing script:', script.send)
|
console.log('Executing script:', script.send)
|
||||||
this.shell!.write(script.send + '\n')
|
this.shell.write(script.send + '\n')
|
||||||
this.scripts = this.scripts.filter(x => x !== script)
|
this.scripts = this.scripts.filter(x => x !== script)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
@ -197,28 +197,28 @@
|
|||||||
.form-line.align-items-start
|
.form-line.align-items-start
|
||||||
.header
|
.header
|
||||||
.title Ciphers
|
.title Ciphers
|
||||||
.w-50
|
.w-75
|
||||||
div(*ngFor='let alg of supportedAlgorithms.cipher')
|
div(*ngFor='let alg of supportedAlgorithms.cipher')
|
||||||
checkbox([text]='alg', [(ngModel)]='algorithms.cipher[alg]')
|
checkbox([text]='alg', [(ngModel)]='algorithms.cipher[alg]')
|
||||||
|
|
||||||
.form-line.align-items-start
|
.form-line.align-items-start
|
||||||
.header
|
.header
|
||||||
.title Key exchange
|
.title Key exchange
|
||||||
.w-50
|
.w-75
|
||||||
div(*ngFor='let alg of supportedAlgorithms.kex')
|
div(*ngFor='let alg of supportedAlgorithms.kex')
|
||||||
checkbox([text]='alg', [(ngModel)]='algorithms.kex[alg]')
|
checkbox([text]='alg', [(ngModel)]='algorithms.kex[alg]')
|
||||||
|
|
||||||
.form-line.align-items-start
|
.form-line.align-items-start
|
||||||
.header
|
.header
|
||||||
.title HMAC
|
.title HMAC
|
||||||
.w-50
|
.w-75
|
||||||
div(*ngFor='let alg of supportedAlgorithms.hmac')
|
div(*ngFor='let alg of supportedAlgorithms.hmac')
|
||||||
checkbox([text]='alg', [(ngModel)]='algorithms.hmac[alg]')
|
checkbox([text]='alg', [(ngModel)]='algorithms.hmac[alg]')
|
||||||
|
|
||||||
.form-line.align-items-start
|
.form-line.align-items-start
|
||||||
.header
|
.header
|
||||||
.title Host key
|
.title Host key
|
||||||
.w-50
|
.w-75
|
||||||
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
|
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
|
||||||
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
|
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { ElectronService, HostAppService, ConfigService, PlatformService } from
|
|||||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||||
import { SSHConnection, LoginScript, ForwardedPortConfig, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
|
import { SSHConnection, LoginScript, ForwardedPortConfig, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
|
||||||
import { PromptModalComponent } from './promptModal.component'
|
import { PromptModalComponent } from './promptModal.component'
|
||||||
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
import * as ALGORITHMS from 'ssh2/lib/protocol/constants'
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Component({
|
@Component({
|
||||||
@ -39,15 +39,15 @@ export class EditConnectionModalComponent {
|
|||||||
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
||||||
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
||||||
[SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
|
[SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
|
||||||
[SSHAlgorithmType.HMAC]: 'SUPPORTED_HMAC',
|
[SSHAlgorithmType.HMAC]: 'SUPPORTED_MAC',
|
||||||
}[k]
|
}[k]
|
||||||
const defaultAlg = {
|
const defaultAlg = {
|
||||||
[SSHAlgorithmType.KEX]: 'KEX',
|
[SSHAlgorithmType.KEX]: 'DEFAULT_KEX',
|
||||||
[SSHAlgorithmType.HOSTKEY]: 'SERVER_HOST_KEY',
|
[SSHAlgorithmType.HOSTKEY]: 'DEFAULT_SERVER_HOST_KEY',
|
||||||
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
[SSHAlgorithmType.CIPHER]: 'DEFAULT_CIPHER',
|
||||||
[SSHAlgorithmType.HMAC]: 'HMAC',
|
[SSHAlgorithmType.HMAC]: 'DEFAULT_MAC',
|
||||||
}[k]
|
}[k]
|
||||||
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x)).sort()
|
||||||
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.reconnectOffered = true
|
this.reconnectOffered = true
|
||||||
this.write('Press any key to reconnect\r\n')
|
this.write('Press any key to reconnect\r\n')
|
||||||
this.input$.pipe(first()).subscribe(() => {
|
this.input$.pipe(first()).subscribe(() => {
|
||||||
if (!this.session?.open) {
|
if (!this.session?.open && this.reconnectOffered) {
|
||||||
this.reconnect()
|
this.reconnect()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import colors from 'ansi-colors'
|
import colors from 'ansi-colors'
|
||||||
import { Duplex } from 'stream'
|
import { Duplex } from 'stream'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import { Injectable, NgZone } from '@angular/core'
|
import { Injectable, Injector, NgZone } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { Client } from 'ssh2'
|
import { Client } from 'ssh2'
|
||||||
import { SSH2Stream } from 'ssh2-streams'
|
|
||||||
import * as fs from 'mz/fs'
|
import * as fs from 'mz/fs'
|
||||||
import { exec } from 'child_process'
|
import { exec } from 'child_process'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
@ -25,6 +24,7 @@ export class SSHService {
|
|||||||
private logger: Logger
|
private logger: Logger
|
||||||
|
|
||||||
private constructor (
|
private constructor (
|
||||||
|
private injector: Injector,
|
||||||
private log: LogService,
|
private log: LogService,
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private ngbModal: NgbModal,
|
private ngbModal: NgbModal,
|
||||||
@ -39,7 +39,7 @@ export class SSHService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createSession (connection: SSHConnection): SSHSession {
|
createSession (connection: SSHConnection): SSHSession {
|
||||||
const session = new SSHSession(connection)
|
const session = new SSHSession(this.injector, connection)
|
||||||
session.logger = this.log.create(`ssh-${connection.host}-${connection.port}`)
|
session.logger = this.log.create(`ssh-${connection.host}-${connection.port}`)
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
@ -114,7 +114,6 @@ export class SSHService {
|
|||||||
const ssh = new Client()
|
const ssh = new Client()
|
||||||
session.ssh = ssh
|
session.ssh = ssh
|
||||||
let connected = false
|
let connected = false
|
||||||
let savedPassword: string|null = null
|
|
||||||
const algorithms = {}
|
const algorithms = {}
|
||||||
for (const key of Object.keys(session.connection.algorithms ?? {})) {
|
for (const key of Object.keys(session.connection.algorithms ?? {})) {
|
||||||
algorithms[key] = session.connection.algorithms![key].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
algorithms[key] = session.connection.algorithms![key].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
@ -123,8 +122,8 @@ export class SSHService {
|
|||||||
const resultPromise: Promise<void> = new Promise(async (resolve, reject) => {
|
const resultPromise: Promise<void> = new Promise(async (resolve, reject) => {
|
||||||
ssh.on('ready', () => {
|
ssh.on('ready', () => {
|
||||||
connected = true
|
connected = true
|
||||||
if (savedPassword) {
|
if (session.savedPassword) {
|
||||||
this.passwordStorage.savePassword(session.connection, savedPassword)
|
this.passwordStorage.savePassword(session.connection, session.savedPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const fw of session.connection.forwardedPorts ?? []) {
|
for (const fw of session.connection.forwardedPorts ?? []) {
|
||||||
@ -133,6 +132,9 @@ export class SSHService {
|
|||||||
|
|
||||||
this.zone.run(resolve)
|
this.zone.run(resolve)
|
||||||
})
|
})
|
||||||
|
ssh.on('handshake', negotiated => {
|
||||||
|
this.logger.info('Handshake complete:', negotiated)
|
||||||
|
})
|
||||||
ssh.on('error', error => {
|
ssh.on('error', error => {
|
||||||
if (error.message === 'All configured authentication methods failed') {
|
if (error.message === 'All configured authentication methods failed') {
|
||||||
this.passwordStorage.deletePassword(session.connection)
|
this.passwordStorage.deletePassword(session.connection)
|
||||||
@ -197,7 +199,7 @@ export class SSHService {
|
|||||||
agent = process.env.SSH_AUTH_SOCK!
|
agent = process.env.SSH_AUTH_SOCK!
|
||||||
}
|
}
|
||||||
|
|
||||||
const authMethodsLeft = ['none']
|
session.authMethodsLeft = ['none']
|
||||||
if (!session.connection.auth || session.connection.auth === 'publicKey') {
|
if (!session.connection.auth || session.connection.auth === 'publicKey') {
|
||||||
try {
|
try {
|
||||||
privateKey = await this.loadPrivateKeyForSession(session)
|
privateKey = await this.loadPrivateKeyForSession(session)
|
||||||
@ -207,23 +209,23 @@ export class SSHService {
|
|||||||
if (!privateKey) {
|
if (!privateKey) {
|
||||||
session.emitServiceMessage(colors.bgYellow.yellow.black(' ! ') + ` Private key auth selected, but no key is loaded`)
|
session.emitServiceMessage(colors.bgYellow.yellow.black(' ! ') + ` Private key auth selected, but no key is loaded`)
|
||||||
} else {
|
} else {
|
||||||
authMethodsLeft.push('publickey')
|
session.authMethodsLeft.push('publickey')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!session.connection.auth || session.connection.auth === 'agent') {
|
if (!session.connection.auth || session.connection.auth === 'agent') {
|
||||||
if (!agent) {
|
if (!agent) {
|
||||||
session.emitServiceMessage(colors.bgYellow.yellow.black(' ! ') + ` Agent auth selected, but no running agent is detected`)
|
session.emitServiceMessage(colors.bgYellow.yellow.black(' ! ') + ` Agent auth selected, but no running agent is detected`)
|
||||||
} else {
|
} else {
|
||||||
authMethodsLeft.push('agent')
|
session.authMethodsLeft.push('agent')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!session.connection.auth || session.connection.auth === 'password') {
|
if (!session.connection.auth || session.connection.auth === 'password') {
|
||||||
authMethodsLeft.push('password')
|
session.authMethodsLeft.push('password')
|
||||||
}
|
}
|
||||||
if (!session.connection.auth || session.connection.auth === 'keyboardInteractive') {
|
if (!session.connection.auth || session.connection.auth === 'keyboardInteractive') {
|
||||||
authMethodsLeft.push('keyboard-interactive')
|
session.authMethodsLeft.push('keyboard-interactive')
|
||||||
}
|
}
|
||||||
authMethodsLeft.push('hostbased')
|
session.authMethodsLeft.push('hostbased')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (session.connection.proxyCommand) {
|
if (session.connection.proxyCommand) {
|
||||||
@ -257,19 +259,10 @@ export class SSHService {
|
|||||||
},
|
},
|
||||||
hostHash: 'sha256' as any,
|
hostHash: 'sha256' as any,
|
||||||
algorithms,
|
algorithms,
|
||||||
authHandler: methodsLeft => {
|
authHandler: (methodsLeft, partialSuccess, callback) => {
|
||||||
while (true) {
|
this.zone.run(async () => {
|
||||||
const method = authMethodsLeft.shift()
|
callback(await session.handleAuth(methodsLeft))
|
||||||
if (!method) {
|
})
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (methodsLeft && !methodsLeft.includes(method) && method !== 'agent') {
|
|
||||||
// Agent can still be used even if not in methodsLeft
|
|
||||||
this.logger.info('Server does not support auth method', method)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return method
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
} as any)
|
} as any)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -277,41 +270,6 @@ export class SSHService {
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
let keychainPasswordUsed = false
|
|
||||||
|
|
||||||
;(ssh as any).config.password = () => this.zone.run(async () => {
|
|
||||||
if (session.connection.password) {
|
|
||||||
log('Using preset password')
|
|
||||||
return session.connection.password
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keychainPasswordUsed) {
|
|
||||||
const password = await this.passwordStorage.loadPassword(session.connection)
|
|
||||||
if (password) {
|
|
||||||
log('Trying saved password')
|
|
||||||
keychainPasswordUsed = true
|
|
||||||
return password
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const modal = this.ngbModal.open(PromptModalComponent)
|
|
||||||
modal.componentInstance.prompt = `Password for ${session.connection.user}@${session.connection.host}`
|
|
||||||
modal.componentInstance.password = true
|
|
||||||
modal.componentInstance.showRememberCheckbox = true
|
|
||||||
try {
|
|
||||||
const result = await modal.result
|
|
||||||
if (result) {
|
|
||||||
if (result.remember) {
|
|
||||||
savedPassword = result.value
|
|
||||||
}
|
|
||||||
return result.value
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
} catch {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return resultPromise
|
return resultPromise
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,9 +437,3 @@ export class ProxyCommandStream extends Duplex {
|
|||||||
callback(error)
|
callback(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable */
|
|
||||||
const _authPassword = SSH2Stream.prototype.authPassword
|
|
||||||
SSH2Stream.prototype.authPassword = async function (username, passwordFn: any) {
|
|
||||||
_authPassword.bind(this)(username, await passwordFn())
|
|
||||||
} as any
|
|
||||||
|
@ -2,26 +2,11 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@types/node@*", "@types/node@14.14.31":
|
"@types/node@14.14.31":
|
||||||
version "14.14.31"
|
version "14.14.31"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
||||||
integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==
|
integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==
|
||||||
|
|
||||||
"@types/ssh2-streams@*":
|
|
||||||
version "0.1.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.7.tgz#bf79349ec85a4dfb5b3fd9f4a05af729121f07e6"
|
|
||||||
integrity sha512-cQNV72C+BOG7G8WNGarTQdB2Ii37cJlWatSpx5zTYxtI2ZvUt2lbq6Nc2XZ4kbge28V7Xe5KYYr82d96/rDMnQ==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
|
|
||||||
"@types/ssh2@^0.5.35":
|
|
||||||
version "0.5.46"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.46.tgz#e12341a242aea0e98ac2dec89e039bf421fd3584"
|
|
||||||
integrity sha512-1pC8FHrMPYdkLoUOwTYYifnSEPzAFZRsp3JFC/vokQ+dRrVI+hDBwz0SNmQ3pL6h39OSZlPs0uCG7wKJkftnaA==
|
|
||||||
dependencies:
|
|
||||||
"@types/node" "*"
|
|
||||||
"@types/ssh2-streams" "*"
|
|
||||||
|
|
||||||
ansi-colors@^4.1.1:
|
ansi-colors@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||||
@ -32,7 +17,7 @@ ansi-regex@^6.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.0.tgz#ecc7f5933cbe5ac7b33e209a5ff409ab1669c6b2"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.0.tgz#ecc7f5933cbe5ac7b33e209a5ff409ab1669c6b2"
|
||||||
integrity sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==
|
integrity sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==
|
||||||
|
|
||||||
asn1@~0.2.0, asn1@~0.2.3:
|
asn1@~0.2.3:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||||
@ -54,7 +39,7 @@ balanced-match@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2:
|
bcrypt-pbkdf@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||||
@ -265,30 +250,6 @@ sprintf@0.1.x:
|
|||||||
resolved "https://registry.yarnpkg.com/sprintf/-/sprintf-0.1.5.tgz#8f83e39a9317c1a502cb7db8050e51c679f6edcf"
|
resolved "https://registry.yarnpkg.com/sprintf/-/sprintf-0.1.5.tgz#8f83e39a9317c1a502cb7db8050e51c679f6edcf"
|
||||||
integrity sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=
|
integrity sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=
|
||||||
|
|
||||||
ssh2-streams@Eugeny/ssh2-streams#75f6d3425d071ac73a18fd46e2f5e738bfe897c5:
|
|
||||||
version "0.4.10"
|
|
||||||
resolved "https://codeload.github.com/Eugeny/ssh2-streams/tar.gz/75f6d3425d071ac73a18fd46e2f5e738bfe897c5"
|
|
||||||
dependencies:
|
|
||||||
asn1 "~0.2.0"
|
|
||||||
bcrypt-pbkdf "^1.0.2"
|
|
||||||
streamsearch "~0.1.2"
|
|
||||||
|
|
||||||
ssh2-streams@~0.4.10:
|
|
||||||
version "0.4.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.10.tgz#48ef7e8a0e39d8f2921c30521d56dacb31d23a34"
|
|
||||||
integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==
|
|
||||||
dependencies:
|
|
||||||
asn1 "~0.2.0"
|
|
||||||
bcrypt-pbkdf "^1.0.2"
|
|
||||||
streamsearch "~0.1.2"
|
|
||||||
|
|
||||||
ssh2@^0.8.9:
|
|
||||||
version "0.8.9"
|
|
||||||
resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.9.tgz#54da3a6c4ba3daf0d8477a538a481326091815f3"
|
|
||||||
integrity sha512-GmoNPxWDMkVpMFa9LVVzQZHF6EW3WKmBwL+4/GeILf2hFmix5Isxm7Amamo8o7bHiU0tC+wXsGcUXOxp8ChPaw==
|
|
||||||
dependencies:
|
|
||||||
ssh2-streams "~0.4.10"
|
|
||||||
|
|
||||||
sshpk@Eugeny/node-sshpk#89ed17dfae425a8b629873c8337e77d26838c04f:
|
sshpk@Eugeny/node-sshpk#89ed17dfae425a8b629873c8337e77d26838c04f:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://codeload.github.com/Eugeny/node-sshpk/tar.gz/89ed17dfae425a8b629873c8337e77d26838c04f"
|
resolved "https://codeload.github.com/Eugeny/node-sshpk/tar.gz/89ed17dfae425a8b629873c8337e77d26838c04f"
|
||||||
@ -308,11 +269,6 @@ stack-trace@0.0.x:
|
|||||||
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
|
||||||
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
|
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
|
||||||
|
|
||||||
streamsearch@~0.1.2:
|
|
||||||
version "0.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
|
||||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
|
||||||
|
|
||||||
strip-ansi@^7.0.0:
|
strip-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.0.tgz#1dc49b980c3a4100366617adac59327eefdefcb0"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.0.tgz#1dc49b980c3a4100366617adac59327eefdefcb0"
|
||||||
|
@ -99,6 +99,8 @@ module.exports = options => {
|
|||||||
'path',
|
'path',
|
||||||
'readline',
|
'readline',
|
||||||
'serialport',
|
'serialport',
|
||||||
|
'ssh2',
|
||||||
|
'ssh2/lib/protocol/constants',
|
||||||
'socksv5',
|
'socksv5',
|
||||||
'stream',
|
'stream',
|
||||||
'windows-native-registry',
|
'windows-native-registry',
|
||||||
|
18
yarn.lock
18
yarn.lock
@ -987,7 +987,7 @@ asar@^3.0.0, asar@^3.0.3:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@types/glob" "^7.1.1"
|
"@types/glob" "^7.1.1"
|
||||||
|
|
||||||
asn1@~0.2.0, asn1@~0.2.3:
|
asn1@~0.2.3:
|
||||||
version "0.2.4"
|
version "0.2.4"
|
||||||
resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz"
|
resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz"
|
||||||
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||||
@ -1141,7 +1141,7 @@ base@^0.11.1:
|
|||||||
mixin-deep "^1.2.0"
|
mixin-deep "^1.2.0"
|
||||||
pascalcase "^0.1.1"
|
pascalcase "^0.1.1"
|
||||||
|
|
||||||
bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2:
|
bcrypt-pbkdf@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
|
||||||
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||||
@ -7586,15 +7586,6 @@ sprintf-js@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
ssh2-streams@^0.4.10:
|
|
||||||
version "0.4.10"
|
|
||||||
resolved "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz"
|
|
||||||
integrity sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==
|
|
||||||
dependencies:
|
|
||||||
asn1 "~0.2.0"
|
|
||||||
bcrypt-pbkdf "^1.0.2"
|
|
||||||
streamsearch "~0.1.2"
|
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz"
|
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz"
|
||||||
@ -7658,11 +7649,6 @@ stream-shift@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz"
|
||||||
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
|
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
|
||||||
|
|
||||||
streamsearch@~0.1.2:
|
|
||||||
version "0.1.2"
|
|
||||||
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz"
|
|
||||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
|
||||||
|
|
||||||
string-width@^1.0.1:
|
string-width@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user