Start work on SSH askpass implementation

This commit is contained in:
Kovid Goyal 2022-03-10 17:26:47 +05:30
parent 910565aa7c
commit 3b724c8415
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 72 additions and 0 deletions

View File

@ -701,6 +701,17 @@ def callback_(res: Dict[str, Any], x: int, boss: Boss) -> None:
cmd += ['-c', c]
self._run_kitten('ask', cmd, window=window, custom_callback=callback_, default_data={'response': ''})
def get_line(
self, msg: str, # can contain newlines and ANSI formatting
callback: Callable[..., None], # called with the answer or empty string when aborted
window: Optional[Window] = None, # the window associated with the confirmation
is_password: bool = False
) -> None:
def callback_(res: Dict[str, Any], x: int, boss: Boss) -> None:
callback(res.get('response') or '')
cmd = ['--type', 'password' if is_password else 'line', '--message', msg]
self._run_kitten('ask', cmd, window=window, custom_callback=callback_, default_data={'response': ''})
def confirm_tab_close(self, tab: Tab) -> None:
x = get_options().confirm_os_window_close
num = tab.number_of_windows_with_running_programs if x < 0 else len(tab)

View File

@ -1084,6 +1084,7 @@ dispatch_dcs(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
} else IF_SIMPLE_PREFIX("kitty-print|", screen_handle_print)
} else IF_SIMPLE_PREFIX("kitty-echo|", screen_handle_echo)
} else IF_SIMPLE_PREFIX("kitty-ssh|", screen_handle_ssh)
} else IF_SIMPLE_PREFIX("kitty-askpass|", screen_handle_askpass)
#undef IF_SIMPLE_PREFIX
} else {
REPORT_ERROR("Unrecognized DCS @ code: 0x%x", screen->parser_buf[1]);

View File

@ -2114,6 +2114,12 @@ screen_handle_ssh(Screen *self, PyObject *msg) {
CALLBACK("handle_remote_ssh", "O", msg);
}
void
screen_handle_askpass(Screen *self, PyObject *msg) {
CALLBACK("handle_remote_askpass", "O", msg);
}
void
screen_request_capabilities(Screen *self, char c, PyObject *q) {
static char buf[128];

View File

@ -210,6 +210,7 @@ void screen_report_color_stack(Screen *);
void screen_handle_print(Screen *, PyObject *cmd);
void screen_handle_echo(Screen *, PyObject *cmd);
void screen_handle_ssh(Screen *, PyObject *cmd);
void screen_handle_askpass(Screen *, PyObject *cmd);
void screen_designate_charset(Screen *, uint32_t which, uint32_t as);
void screen_use_latin1(Screen *, bool);
void set_title(Screen *self, PyObject*);

View File

@ -885,6 +885,35 @@ def handle_remote_ssh(self, msg: str) -> None:
for line in get_ssh_data(msg, f'{os.getpid()}-{self.id}'):
self.write_to_child(line)
def handle_remote_askpass(self, msg: str) -> None:
from .shm import SharedMemory
with SharedMemory(name=msg, readonly=True) as shm:
shm.seek(1)
data = json.loads(shm.read_data_with_size())
def callback(ans: Any) -> None:
data = json.dumps(ans)
with SharedMemory(name=msg) as shm:
shm.seek(1)
shm.write_data_with_size(data)
shm.flush()
shm.seek(0)
shm.write(b'\x01')
prompt: str = data['prompt']
if data['type'] == 'confirm':
get_boss().confirm(
prompt, callback, window=self, confirm_on_cancel=bool(data.get('confirm_on_cancel')),
confirm_on_accept=bool(data.get('confirm_on_accept')))
elif data['type'] == 'choose':
get_boss().choose(
prompt, callback, *data['choices'], window=self, default=data.get('default', ''))
elif data['type'] == 'get_line':
get_boss().get_line(
prompt, callback, window=self, is_password=bool(data.get('is_password')))
else:
log_error(f'Ignoring ask request with unknown type: {data["type"]}')
def handle_remote_print(self, msg: str) -> None:
text = process_remote_print(msg)
print(text, end='', file=sys.stderr)

View File

@ -0,0 +1,24 @@
#!/usr/bin/env -S kitty +launch
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
import json
import os
import struct
import sys
from kitty.shm import SharedMemory
msg = sys.argv[-1]
prompt = os.environ.get('SSH_ASKPASS_PROMPT', '')
is_confirm = prompt == 'confirm'
ask_cmdline = ['-m', msg, '--type', 'yesno' if is_confirm else 'password']
if is_confirm:
ask_cmdline += ['--default', 'y']
data = json.dumps(ask_cmdline).encode('utf-8')
sz = struct.pack('>I', len(data))
with SharedMemory(size=len(data) + len(sz) + 1, unlink_on_exit=True, prefix=f'askpass-{os.getpid()}-') as shm, open(os.ctermid(), 'wb') as tty:
shm.write(b'\0')
shm.write(sz)
shm.write(data)
shm.flush()
print(f'\x1bP@kitty-ask|{shm.name}\x1b\\', flush=True)