mirror of
https://github.com/Eugeny/tabby.git
synced 2024-12-29 13:35:34 +03:00
more explicit SSH auth options and agent forwarding - fixes #2284, fixes #2511, fixes #2717, fixes #2184
This commit is contained in:
parent
34752ed69e
commit
da21895e40
@ -24,6 +24,7 @@ export interface SSHConnection {
|
||||
host: string
|
||||
port: number
|
||||
user: string
|
||||
auth?: null|'password'|'publicKey'|'agent'|'keyboardInteractive'
|
||||
password?: string
|
||||
privateKey?: string
|
||||
group: string | null
|
||||
@ -36,7 +37,6 @@ export interface SSHConnection {
|
||||
skipBanner?: boolean
|
||||
disableDynamicTitle?: boolean
|
||||
jumpHost?: string
|
||||
agentForward?: boolean
|
||||
|
||||
algorithms?: {[t: string]: string[]}
|
||||
}
|
||||
|
@ -43,6 +43,34 @@
|
||||
)
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Authentication
|
||||
.btn-group.w-100(
|
||||
[(ngModel)]='connection.auth',
|
||||
ngbRadioGroup
|
||||
)
|
||||
label.btn.btn-outline-secondary(ngbButtonLabel)
|
||||
input(type='radio', ngbButton, [value]='null')
|
||||
i.far.fa-lightbulb
|
||||
.m-0 Auto
|
||||
label.btn.btn-outline-secondary(ngbButtonLabel)
|
||||
input(type='radio', ngbButton, [value]='"password"')
|
||||
i.fas.fa-font
|
||||
.m-0 Password
|
||||
label.btn.btn-outline-secondary(ngbButtonLabel)
|
||||
input(type='radio', ngbButton, [value]='"publicKey"')
|
||||
i.fas.fa-key
|
||||
.m-0 Key
|
||||
label.btn.btn-outline-secondary(ngbButtonLabel)
|
||||
input(type='radio', ngbButton, [value]='"agent"')
|
||||
i.fas.fa-user-secret
|
||||
.m-0 Agent
|
||||
label.btn.btn-outline-secondary(ngbButtonLabel)
|
||||
input(type='radio', ngbButton, [value]='"keyboardInteractive"')
|
||||
i.far.fa-keyboard
|
||||
.m-0 Interactive
|
||||
|
||||
.form-line(*ngIf='!connection.auth || connection.auth === "password"')
|
||||
.header
|
||||
.title Password
|
||||
.description(*ngIf='!hasSavedPassword') Save a password in the keychain
|
||||
@ -54,7 +82,7 @@
|
||||
i.fas.fa-trash-alt
|
||||
span Forget
|
||||
|
||||
.form-line
|
||||
.form-line(*ngIf='!connection.auth || connection.auth === "publicKey"')
|
||||
.header
|
||||
.title Private key
|
||||
.description Path to the private key file
|
||||
@ -83,11 +111,6 @@
|
||||
.title X11 forwarding
|
||||
toggle([(ngModel)]='connection.x11')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Allow Agent Forwarding
|
||||
toggle([(ngModel)]='connection.agentForward')
|
||||
|
||||
.form-line
|
||||
.header
|
||||
.title Tab color
|
||||
|
@ -49,6 +49,7 @@ export class EditConnectionModalComponent {
|
||||
this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection)
|
||||
this.connection.algorithms = this.connection.algorithms || {}
|
||||
this.connection.scripts = this.connection.scripts || []
|
||||
this.connection.auth = this.connection.auth || null
|
||||
|
||||
for (const k of Object.values(SSHAlgorithmType)) {
|
||||
if (!this.connection.algorithms[k]) {
|
||||
|
@ -160,6 +160,9 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
}
|
||||
|
||||
async canClose (): Promise<boolean> {
|
||||
if (!this.session?.open) {
|
||||
return true
|
||||
}
|
||||
return (await this.electron.showMessageBox(
|
||||
this.hostApp.getWindow(),
|
||||
{
|
||||
|
@ -165,8 +165,13 @@ export class SSHService {
|
||||
const modal = this.ngbModal.open(PromptModalComponent)
|
||||
modal.componentInstance.prompt = prompt.prompt
|
||||
modal.componentInstance.password = !prompt.echo
|
||||
const result = await modal.result
|
||||
results.push(result ? result.value : '')
|
||||
|
||||
try {
|
||||
const result = await modal.result
|
||||
results.push(result ? result.value : '')
|
||||
} catch {
|
||||
results.push('')
|
||||
}
|
||||
}
|
||||
finish(results)
|
||||
}))
|
||||
@ -194,6 +199,29 @@ export class SSHService {
|
||||
agent = process.env.SSH_AUTH_SOCK as string
|
||||
}
|
||||
|
||||
const authMethodsLeft = ['none']
|
||||
if (!session.connection.auth || session.connection.auth === 'password') {
|
||||
authMethodsLeft.push('password')
|
||||
}
|
||||
if (!session.connection.auth || session.connection.auth === 'publicKey') {
|
||||
if (!privateKey) {
|
||||
log('\r\nPrivate key auth selected, but no key is loaded\r\n')
|
||||
} else {
|
||||
authMethodsLeft.push('publickey')
|
||||
}
|
||||
}
|
||||
if (!session.connection.auth || session.connection.auth === 'agent') {
|
||||
if (!agent) {
|
||||
log('\r\nAgent auth selected, but no running agent is detected\r\n')
|
||||
} else {
|
||||
authMethodsLeft.push('agent')
|
||||
}
|
||||
}
|
||||
if (!session.connection.auth || session.connection.auth === 'keyboardInteractive') {
|
||||
authMethodsLeft.push('keyboard-interactive')
|
||||
}
|
||||
authMethodsLeft.push('hostbased')
|
||||
|
||||
try {
|
||||
ssh.connect({
|
||||
host: session.connection.host,
|
||||
@ -202,8 +230,8 @@ export class SSHService {
|
||||
password: session.connection.privateKey ? undefined : '',
|
||||
privateKey: privateKey || undefined,
|
||||
tryKeyboard: true,
|
||||
agent: session.connection.agentForward && agent || undefined,
|
||||
agentForward: session.connection.agentForward && !!agent,
|
||||
agent: agent || undefined,
|
||||
agentForward: (!session.connection.auth || session.connection.auth === 'agent') && !!agent,
|
||||
keepaliveInterval: session.connection.keepaliveInterval,
|
||||
keepaliveCountMax: session.connection.keepaliveCountMax,
|
||||
readyTimeout: session.connection.readyTimeout,
|
||||
@ -215,7 +243,21 @@ export class SSHService {
|
||||
hostHash: 'sha256' as any,
|
||||
algorithms: session.connection.algorithms,
|
||||
sock: session.jumpStream,
|
||||
})
|
||||
authHandler: methodsLeft => {
|
||||
while (true) {
|
||||
let method = 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
|
||||
}
|
||||
return method
|
||||
}
|
||||
},
|
||||
} as any)
|
||||
} catch (e) {
|
||||
this.toastr.error(e.message)
|
||||
reject(e)
|
||||
|
Loading…
Reference in New Issue
Block a user