Git - implement SSH_ASKPASS handler (#159573)

This commit is contained in:
Ladislau Szomoru
2022-09-07 15:59:40 +02:00
committed by GitHub
parent c399c8cce7
commit a6272c9416
5 changed files with 91 additions and 11 deletions

View File

@@ -3,13 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { window, InputBoxOptions, Uri, Disposable, workspace } from 'vscode';
import * as nls from 'vscode-nls';
import { window, InputBoxOptions, Uri, Disposable, workspace, QuickPickOptions } from 'vscode';
import { IDisposable, EmptyDisposable, toDisposable } from './util';
import * as path from 'path';
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
import { CredentialsProvider, Credentials } from './api/git';
import { ITerminalEnvironmentProvider } from './terminal';
const localize = nls.loadMessageBundle();
export class Askpass implements IIPCHandler, ITerminalEnvironmentProvider {
private env: { [key: string]: string };
@@ -23,14 +26,22 @@ export class Askpass implements IIPCHandler, ITerminalEnvironmentProvider {
}
this.env = {
// GIT_ASKPASS
GIT_ASKPASS: path.join(__dirname, this.ipc ? 'askpass.sh' : 'askpass-empty.sh'),
// SSH_ASKPASS
SSH_ASKPASS: path.join(__dirname, this.ipc ? 'ssh-askpass.sh' : 'ssh-askpass-empty.sh'),
SSH_ASKPASS_REQUIRE: 'force',
// VSCODE_GIT_ASKPASS
VSCODE_GIT_ASKPASS_NODE: process.execPath,
VSCODE_GIT_ASKPASS_EXTRA_ARGS: (process.versions['electron'] && process.versions['microsoft-build']) ? '--ms-enable-electron-run-as-node' : '',
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js'),
};
}
async handle({ request, host }: { request: string; host: string }): Promise<string> {
async handle(payload:
{ askpassType: 'https'; request: string; host: string } |
{ askpassType: 'ssh'; request: string; host?: string; file?: string; fingerprint?: string }
): Promise<string> {
const config = workspace.getConfiguration('git', null);
const enabled = config.get<boolean>('enabled');
@@ -38,6 +49,16 @@ export class Askpass implements IIPCHandler, ITerminalEnvironmentProvider {
return '';
}
// https
if (payload.askpassType === 'https') {
return await this.handleAskpass(payload.request, payload.host);
}
// ssh
return await this.handleSSHAskpass(payload.request, payload.host, payload.file, payload.fingerprint);
}
async handleAskpass(request: string, host: string): Promise<string> {
const uri = Uri.parse(host);
const authority = uri.authority.replace(/^.*@/, '');
const password = /password/i.test(request);
@@ -72,6 +93,33 @@ export class Askpass implements IIPCHandler, ITerminalEnvironmentProvider {
return await window.showInputBox(options) || '';
}
async handleSSHAskpass(request: string, host?: string, file?: string, fingerprint?: string): Promise<string> {
// passphrase
if (/passphrase/i.test(request)) {
const options: InputBoxOptions = {
password: true,
placeHolder: localize('ssh passphrase', "Passphrase"),
prompt: `SSH Key: ${file}`,
ignoreFocusOut: true
};
return await window.showInputBox(options) || '';
}
// authenticity
const options: QuickPickOptions = {
canPickMany: false,
ignoreFocusOut: true,
placeHolder: localize('ssh authenticity prompt', "Are you sure you want to continue connecting?"),
title: localize('ssh authenticity title', "\"{0}\" has fingerprint \"{1}\"", host, fingerprint)
};
const items = [
localize('ssh authenticity prompt yes', "yes"),
localize('ssh authenticity prompt no', "no")
];
return await window.showQuickPick(items, options) ?? '';
}
getEnv(): { [key: string]: string } {
const config = workspace.getConfiguration('git');
return config.get<boolean>('useIntegratedAskPass') ? this.env : {};