Make allow_remote_control a little more fine grained

Also, only respect listen_on if there is a possiblility of rc commands
over it being accepted
This commit is contained in:
Kovid Goyal 2022-08-15 20:51:11 +05:30
parent df5e6e1563
commit d027f524ce
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 79 additions and 48 deletions

View File

@ -258,7 +258,11 @@ class Boss:
# we dont allow reloading the config file to change
# allow_remote_control
self.allow_remote_control = opts.allow_remote_control
if args.listen_on:
if self.allow_remote_control in ('y', 'yes', 'true'):
self.allow_remote_control = 'y'
elif self.allow_remote_control in ('n', 'no', 'false'):
self.allow_remote_control = 'n'
if args.listen_on and self.allow_remote_control in ('y', 'socket', 'socket-only', 'password'):
listen_fd = listen_on(args.listen_on)
self.prewarm = prewarm
self.child_monitor = ChildMonitor(
@ -447,6 +451,10 @@ class Boss:
from .remote_control import is_cmd_allowed, parse_cmd
response = None
window = window or None
if self.allow_remote_control == 'n':
return {'ok': False, 'error': 'Remote control is disabled'}
if self.allow_remote_control == 'socket-only' and peer_id == 0:
return {'ok': False, 'error': 'Remote control is allowed over a socket only'}
try:
pcmd = parse_cmd(cmd, self.encryption_key)
except Exception as e:
@ -454,10 +462,10 @@ class Boss:
return response
if not pcmd:
return response
allowed_by_channel = (
self.allow_remote_control == 'y' or (peer_id > 0 and self.allow_remote_control == 'socket-only') or
getattr(window, 'allow_remote_control', False))
if allowed_by_channel:
allowed_unconditionally = (
self.allow_remote_control == 'y' or (peer_id > 0 and self.allow_remote_control in ('socket-only', 'socket')) or
(window and window.allow_remote_control))
if allowed_unconditionally:
return self._execute_remote_command(pcmd, window, peer_id)
q = is_cmd_allowed(pcmd, window, peer_id > 0, {})
if q is True:

View File

@ -677,17 +677,18 @@ regardless of this option.
--listen-on
Listen on the specified socket address for control messages. For example,
:option:`{appname} --listen-on`=unix:/tmp/mykitty or
:option:`{appname} --listen-on`=tcp:localhost:12345. On Linux systems, you can
also use abstract UNIX sockets, not associated with a file, like this:
:option:`{appname} --listen-on`=unix:@mykitty. Environment variables are
expanded and relative paths are resolved with respect to the temporary
directory. To control kitty, you can send commands to it with
:italic:`{appname} @` using the :option:`{appname} @ --to` option to specify
this address. Note that if you run :italic:`{appname} @` within a kitty window, there is
no need to specify the :option:`{appname} @ --to` option as it will
automatically read from the environment. For UNIX sockets, this can also be
specified in :file:`{conf_name}.conf`.
:option:`{appname} --listen-on`=unix:/tmp/mykitty or :option:`{appname}
--listen-on`=tcp:localhost:12345. On Linux systems, you can also use abstract
UNIX sockets, not associated with a file, like this: :option:`{appname}
--listen-on`=unix:@mykitty. Environment variables are expanded and relative
paths are resolved with respect to the temporary directory. To control kitty,
you can send commands to it with :italic:`{appname} @` using the
:option:`{appname} @ --to` option to specify this address. Note that if you run
:italic:`{appname} @` within a kitty window, there is no need to specify the
:option:`{appname} @ --to` option as it will automatically read from the
environment. Note that this will be ignored unless :opt:`allow_remote_control`
is set to either: :code:`yes`, :code:`socket` or :code:`socket-only`. For UNIX
sockets, this can also be specified in :file:`{conf_name}.conf`.
--start-as

View File

@ -2713,35 +2713,50 @@ that is used to check every remote control command. See :ref:`rc_custom_auth` fo
Relative paths are resolved from the kitty configuration directory.
''')
opt('allow_remote_control', 'no',
option_type='allow_remote_control',
opt('allow_remote_control', 'password', choices=('password', 'socket-only', 'socket', 'no', 'n', 'false', 'yes', 'y', 'true'),
long_text='''
Allow other programs to control kitty. If you turn this on, other programs can
control all aspects of kitty, including sending text to kitty windows, opening
new windows, closing windows, reading the content of windows, etc. Note that
this even works over SSH connections. You can choose to either allow any program
running within kitty to control it with :code:`yes`, or only allow programs that
connect to the socket (specified with the :opt:`listen_on` config option or
:option:`kitty --listen-on` command line option) with the value
:code:`socket-only`. The latter is useful if you want to prevent programs
running on a remote computer over SSH from controlling kitty. Reloading the
config will not affect this option.
this even works over SSH connections. The default setting of :code:`password`
asks the user for confirmation when a remote control command is received.
The meaning of the various values are:
:code:`password`
Remote control requests received over both the TTY device and the socket are
confirmed based on passwords, see :opt:`remote_control_password`.
:code:`socket-only`
Remote control requests received over a socket are accepted unconditionally.
Requests received over the TTY are denied. See :opt:`listen_on`.
:code:`socket`
Remote control requests received over a socket are accepted unconditionally.
Requests received over the TTY are confirmed based on password.
:code:`no`
Remote control is completely disabled.
:code:`yes`
Remote control requests are always accepted.
'''
)
opt('listen_on', 'none',
long_text='''
Listen to the specified UNIX socket for remote control connections. Note
that this will apply to all kitty instances. It can be overridden by the
:option:`kitty --listen-on` command line option, which supports listening on TCP
socket. This option accepts only UNIX sockets, such as
Listen to the specified UNIX socket for remote control connections. Note that
this will apply to all kitty instances. It can be overridden by the
:option:`kitty --listen-on` command line option, which also supports listening
on a TCP socket. This option accepts only UNIX sockets, such as
:code:`unix:${TEMP}/mykitty` or :code:`unix:@mykitty` (on Linux). Environment
variables are expanded and relative paths are resolved with respect to the
temporary directory. If :code:`{kitty_pid}` is present, then it is replaced
by the PID of the kitty process, otherwise the PID of the kitty process is
appended to the value, with a hyphen. See the help for
:option:`kitty --listen-on` for more details. Changing this option by reloading
the config is not supported.
temporary directory. If :code:`{kitty_pid}` is present, then it is replaced by
the PID of the kitty process, otherwise the PID of the kitty process is
appended to the value, with a hyphen. See the help for :option:`kitty
--listen-on` for more details. Note that this will be ignored unless :opt:`allow_remote_control`
is set to either: :code:`yes`, :code:`socket` or :code:`socket-only`.
Changing this option by reloading the config is not supported.
'''
)

31
kitty/options/parse.py generated
View File

@ -6,18 +6,18 @@ from kitty.conf.utils import (
unit_float
)
from kitty.options.utils import (
action_alias, active_tab_title_template, allow_hyperlinks, allow_remote_control, bell_on_tab,
box_drawing_scale, clear_all_mouse_actions, clear_all_shortcuts, clipboard_control,
clone_source_strategies, config_or_absolute_path, copy_on_select, cursor_text_color,
deprecated_adjust_line_height, deprecated_hide_window_decorations_aliases,
deprecated_macos_show_window_title_in_menubar_alias, deprecated_send_text, disable_ligatures,
edge_width, env, font_features, hide_window_decorations, macos_option_as_alt, macos_titlebar_color,
modify_font, narrow_symbols, optional_edge_width, parse_map, parse_mouse_map, paste_actions,
remote_control_password, resize_draw_strategy, scrollback_lines, scrollback_pager_history_size,
shell_integration, store_multiple, symbol_map, tab_activity_symbol, tab_bar_edge,
tab_bar_margin_height, tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator,
tab_title_template, titlebar_color, to_cursor_shape, to_font_size, to_layout_names, to_modifiers,
url_prefixes, url_style, visual_window_select_characters, window_border_width, window_size
action_alias, active_tab_title_template, allow_hyperlinks, bell_on_tab, box_drawing_scale,
clear_all_mouse_actions, clear_all_shortcuts, clipboard_control, clone_source_strategies,
config_or_absolute_path, copy_on_select, cursor_text_color, deprecated_adjust_line_height,
deprecated_hide_window_decorations_aliases, deprecated_macos_show_window_title_in_menubar_alias,
deprecated_send_text, disable_ligatures, edge_width, env, font_features, hide_window_decorations,
macos_option_as_alt, macos_titlebar_color, modify_font, narrow_symbols, optional_edge_width,
parse_map, parse_mouse_map, paste_actions, remote_control_password, resize_draw_strategy,
scrollback_lines, scrollback_pager_history_size, shell_integration, store_multiple, symbol_map,
tab_activity_symbol, tab_bar_edge, tab_bar_margin_height, tab_bar_min_tabs, tab_fade,
tab_font_style, tab_separator, tab_title_template, titlebar_color, to_cursor_shape, to_font_size,
to_layout_names, to_modifiers, url_prefixes, url_style, visual_window_select_characters,
window_border_width, window_size
)
@ -54,7 +54,12 @@ class Parser:
ans['allow_hyperlinks'] = allow_hyperlinks(val)
def allow_remote_control(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['allow_remote_control'] = allow_remote_control(val)
val = val.lower()
if val not in self.choices_for_allow_remote_control:
raise ValueError(f"The value {val} is not a valid choice for allow_remote_control")
ans["allow_remote_control"] = val
choices_for_allow_remote_control = frozenset(('password', 'socket-only', 'socket', 'no', 'n', 'false', 'yes', 'y', 'true'))
def background(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['background'] = to_color(val)

View File

@ -14,6 +14,7 @@ import kitty.types
if typing.TYPE_CHECKING:
choices_for_allow_cloning = typing.Literal['yes', 'y', 'true', 'no', 'n', 'false', 'ask']
choices_for_allow_remote_control = typing.Literal['password', 'socket-only', 'socket', 'no', 'n', 'false', 'yes', 'y', 'true']
choices_for_background_image_layout = typing.Literal['mirror-tiled', 'scaled', 'tiled', 'clamped']
choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'hand']
choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11']
@ -30,6 +31,7 @@ if typing.TYPE_CHECKING:
choices_for_window_logo_position = typing.Literal['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']
else:
choices_for_allow_cloning = str
choices_for_allow_remote_control = str
choices_for_background_image_layout = str
choices_for_default_pointer_shape = str
choices_for_linux_display_server = str
@ -467,7 +469,7 @@ class Options:
active_tab_title_template: typing.Optional[str] = None
allow_cloning: choices_for_allow_cloning = 'ask'
allow_hyperlinks: int = 1
allow_remote_control: str = 'n'
allow_remote_control: choices_for_allow_remote_control = 'password'
background: Color = Color(0, 0, 0)
background_image: typing.Optional[str] = None
background_image_layout: choices_for_background_image_layout = 'tiled'