summaryrefslogtreecommitdiff
path: root/kvmd/apps/vnc/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'kvmd/apps/vnc/server.py')
-rw-r--r--kvmd/apps/vnc/server.py104
1 files changed, 66 insertions, 38 deletions
diff --git a/kvmd/apps/vnc/server.py b/kvmd/apps/vnc/server.py
index e9872b90..084f9b0f 100644
--- a/kvmd/apps/vnc/server.py
+++ b/kvmd/apps/vnc/server.py
@@ -39,6 +39,9 @@ from ... import aiotools
from .rfb import RfbClient
from .rfb.errors import RfbError
+from .vncauth import VncAuthKvmdCredentials
+from .vncauth import VncAuthManager
+
from .kvmd import KvmdClient
from .streamer import StreamerError
@@ -66,11 +69,14 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
desired_fps: int,
symmap: Dict[int, str],
+ vnc_credentials: Dict[str, VncAuthKvmdCredentials],
shared_params: _SharedParams,
) -> None:
- super().__init__(reader, writer, **dataclasses.asdict(shared_params))
+ self.__vnc_credentials = vnc_credentials
+
+ super().__init__(reader, writer, vnc_passwds=list(vnc_credentials), **dataclasses.asdict(shared_params))
self.__kvmd = kvmd
self.__streamer = streamer
@@ -208,12 +214,18 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
# =====
- async def _authorize(self, user: str, passwd: str) -> bool:
+ async def _authorize_userpass(self, user: str, passwd: str) -> bool:
if (await self.__kvmd.authorize(user, passwd)):
self.__authorized.set_result((user, passwd))
return True
return False
+ async def _on_authorized_vnc_passwd(self, passwd: str) -> str:
+ kc = self.__vnc_credentials[passwd]
+ if (await self._authorize_userpass(kc.user, kc.passwd)):
+ return kc.user
+ return ""
+
async def _on_key_event(self, code: int, state: bool) -> None:
if (web_name := self.__symmap.get(code)) is not None: # noqa: E203,E231
await self.__ws_writer_queue.put({
@@ -258,7 +270,7 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
# =====
-class VncServer:
+class VncServer: # pylint: disable=too-many-instance-attributes
def __init__(
self,
host: str,
@@ -267,6 +279,7 @@ class VncServer:
kvmd: KvmdClient,
streamer: StreamerClient,
+ vnc_auth_manager: VncAuthManager,
desired_fps: int,
symmap: Dict[int, str],
@@ -276,43 +289,58 @@ class VncServer:
self.__port = port
self.__max_clients = max_clients
- self.__client_kwargs = {
- "kvmd": kvmd,
- "streamer": streamer,
- "desired_fps": desired_fps,
- "symmap": symmap,
- "shared_params": _SharedParams(),
- }
-
- def run(self) -> None:
- logger = get_logger(0)
- logger.info("Listening VNC on TCP [%s]:%d ...", self.__host, self.__port)
+ self.__kvmd = kvmd
+ self.__streamer = streamer
+ self.__vnc_auth_manager = vnc_auth_manager
- with contextlib.closing(socket.socket(socket.AF_INET6, socket.SOCK_STREAM)) as sock:
- sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
- sock.bind((self.__host, self.__port))
+ self.__desired_fps = desired_fps
+ self.__symmap = symmap
- loop = asyncio.get_event_loop()
- server = loop.run_until_complete(asyncio.start_server(
- client_connected_cb=self.__handle_client,
- sock=sock,
- backlog=self.__max_clients,
- loop=loop,
- ))
+ self.__shared_params = _SharedParams()
- try:
- loop.run_forever()
- except (SystemExit, KeyboardInterrupt):
- pass
- finally:
- server.close()
- loop.run_until_complete(server.wait_closed())
- tasks = asyncio.Task.all_tasks()
- for task in tasks:
- task.cancel()
- loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))
- loop.close()
- logger.info("Bye-bye")
+ def run(self) -> None:
+ logger = get_logger(0)
+ loop = asyncio.get_event_loop()
+ try:
+ if not loop.run_until_complete(self.__vnc_auth_manager.read_credentials())[1]:
+ raise SystemExit(1)
+
+ logger.info("Listening VNC on TCP [%s]:%d ...", self.__host, self.__port)
+
+ with contextlib.closing(socket.socket(socket.AF_INET6, socket.SOCK_STREAM)) as sock:
+ sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
+ sock.bind((self.__host, self.__port))
+
+ server = loop.run_until_complete(asyncio.start_server(
+ client_connected_cb=self.__handle_client,
+ sock=sock,
+ backlog=self.__max_clients,
+ loop=loop,
+ ))
+
+ try:
+ loop.run_forever()
+ except (SystemExit, KeyboardInterrupt):
+ pass
+ finally:
+ server.close()
+ loop.run_until_complete(server.wait_closed())
+ finally:
+ tasks = asyncio.Task.all_tasks()
+ for task in tasks:
+ task.cancel()
+ loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True))
+ loop.close()
+ logger.info("Bye-bye")
async def __handle_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
- await _Client(reader, writer, **self.__client_kwargs).run() # type: ignore
+ await _Client(
+ reader=reader,
+ writer=writer,
+ kvmd=self.__kvmd,
+ streamer=self.__streamer,
+ desired_fps=self.__desired_fps,
+ symmap=self.__symmap,
+ vnc_credentials=(await self.__vnc_auth_manager.read_credentials())[0],
+ shared_params=self.__shared_params,
+ ).run() # type: ignore