1284
*/
1285
protected _handleKeyboardInteractive(
1287
>
displayHost: string,
1288
>
username: string,
1289
>
name: string,
1290
>
instructions: string,
1291
>
prompts: readonly ISSHKeyboardInteractivePrompt[],
1292
>
finish: (responses: readonly string[]) => void,
1293
>
cancelConnect: () => void,
1294
>
): string {
1295
>
const requestId = `kbi-${++this._kbiRequestCounter}`;
1296
>
// Wrap finish so it can only fire once — ssh2 ignores duplicate calls,
1297
>
// but we also want to ensure we drop the pending entry exactly once.
1298
>
let settled = false;
1299
>
const finishOnce = (responses: readonly string[]) => {
1300
>
if (settled) {
1301
return;
1302
}
1304
>
this._pendingKbiRequests.delete(requestId);
1305
>
finish(responses);
1306
>
};
1307
>
this._pendingKbiRequests.set(requestId, { finish: finishOnce, cancelConnect });
1308
>
this._logService.info(`${LOG_PREFIX} keyboard-interactive challenge from ${displayHost}: ${prompts.length} prompt(s)`);
1309
>
this._onDidRequestKeyboardInteractive.fire({
1310
>
requestId,
1311
>
connectionKey,
1312
>
displayHost,
1313
>
username,
1314
>
name,
1315
>
instructions,
1316
>
prompts: prompts.map(p => ({ prompt: p.prompt, echo: p.echo })),
1317
>
});
1318
>
return requestId;
1319
>
}
1320
1321
async respondKeyboardInteractive(requestId: string, responses: readonly string[] | undefined): Promise<void> {
1323
>
if (!pending) {
1324
this._logService.warn(`${LOG_PREFIX} respondKeyboardInteractive: no pending request for ${requestId}`);
1325
return;
1326
}
1328
pending.cancelConnect();
1329
pending.finish([]);