Skip to content
This repository was archived by the owner on Jun 24, 2023. It is now read-only.

Commit

Permalink
Merge branch 'port-to-python'
Browse files Browse the repository at this point in the history
  • Loading branch information
ElliotKillick committed Aug 7, 2021
2 parents 999ea16 + d9c052c commit 4d276ff
Show file tree
Hide file tree
Showing 24 changed files with 430 additions and 307 deletions.
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License

Copyright (C) 2021 Elliot Killick <[email protected]>
Copyright (C) 2021 Demi Marie Obenour <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
19 changes: 11 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ PKGNAME = qubes-video-companion

BINDIR ?= /usr/bin
DATADIR ?= /usr/share
QREXECDIR ?= /etc/qubes-rpc
SYSCONFDIR ?= /etc
QREXECDIR ?= $(SYSCONFDIR)/qubes-rpc

INSTALL_DIR = install -d
INSTALL_PROGRAM = install -D
Expand All @@ -25,9 +26,13 @@ build:

install-vm: install-both
$(INSTALL_DIR) $(DESTDIR)$(BINDIR)
$(INSTALL_PROGRAM) video/$(PKGNAME) $(DESTDIR)$(BINDIR)
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/video
$(INSTALL_PROGRAM) video/setup.sh video/receiver.sh video/destroy.sh video/common.sh $(DESTDIR)$(DATADIR)/$(PKGNAME)/video
$(INSTALL_PROGRAM) receiver/$(PKGNAME) $(DESTDIR)$(BINDIR)
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/receiver
$(INSTALL_PROGRAM) receiver/setup.sh receiver/receiver.py receiver/destroy.sh receiver/common.sh $(DESTDIR)$(DATADIR)/$(PKGNAME)/receiver
$(INSTALL_DIR) $(DESTDIR)$(SYSCONFDIR)/qubes/rpc-config
echo 'wait-for-session=1' > $(DESTDIR)$(SYSCONFDIR)/qubes/rpc-config/qvc.Webcam
echo 'wait-for-session=1' > $(DESTDIR)$(SYSCONFDIR)/qubes/rpc-config/qvc.ScreenShare
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts
$(INSTALL_DATA) scripts/webcam.html $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts/v4l2loopback
$(INSTALL_PROGRAM) scripts/v4l2loopback/install.sh $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts/v4l2loopback
Expand All @@ -39,10 +44,8 @@ install-dom0: install-both install-policy
install-both:
$(INSTALL_DIR) $(DESTDIR)$(QREXECDIR)
$(INSTALL_PROGRAM) qubes-rpc/services/qvc.Webcam qubes-rpc/services/qvc.ScreenShare $(DESTDIR)$(QREXECDIR)
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/ui
$(INSTALL_PROGRAM) ui/*.py ui/*.sh $(DESTDIR)$(DATADIR)/$(PKGNAME)/ui
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts
$(INSTALL_PROGRAM) scripts/set-webcam-format.sh $(DESTDIR)$(DATADIR)/$(PKGNAME)/scripts
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/$(PKGNAME)/sender
$(INSTALL_PROGRAM) sender/*.py $(DESTDIR)$(DATADIR)/$(PKGNAME)/sender
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/doc/$(PKGNAME)
$(INSTALL_DATA) README.md doc/pipeline.md $(DESTDIR)$(DATADIR)/doc/$(PKGNAME)
$(INSTALL_DIR) $(DESTDIR)$(DATADIR)/doc/$(PKGNAME)/visualizations
Expand Down
2 changes: 1 addition & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ Description: Securely stream webcams and share screens across virtual machines
computational resources and low latency even at Full HD and greater resolutions
at 30 or more frames per second.
.
This package contains all components of Qubes Video companion excluding the
This package contains all components of Qubes Video Companion excluding the
Qubes RPC policies which dom0 enforces.
2 changes: 2 additions & 0 deletions debian/copyright
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ Source: https://github.com/elliotkillick/qubes-video-companion

Files: *
Copyright: 2021 Elliot Killick <[email protected]>
2021 Demi Marie Obenour <[email protected]>
License: MIT
MIT License
.
Copyright (C) 2021 Elliot Killick <[email protected]>
Copyright (C) 2021 Demi Marie Obenour <[email protected]>
.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
4 changes: 2 additions & 2 deletions doc/pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@


## BGRx -> I420 pixel format `videoconvert` in `qvc.ScreenShare`
### `ximagesrc` only outputs in BGRx so it must be converted to I420 which is a supported input format for `v4l2sink` (on the `receiver.sh` side)
### `ximagesrc` only outputs in BGRx so it must be converted to I420 which is a supported input format for `v4l2sink` (on the `receiver.py` side)
- This video conversion is done on the side of the sending machine as to ensure the attack surface of the recipient stays as small as possible

# Video Receiver (`receiver.sh`)
# Video Receiver (`receiver.py`)

## capsfilter
### This is used to limit our attack surface to the given capabilities
Expand Down
1 change: 1 addition & 0 deletions doc/qubes-video-companion.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ video_source
AUTHORS
=======
| Elliot Killick <elliotkillick at zohomail dot eu>
| Demi Marie Obenour <demi at invisiblethingslab dot com>
36 changes: 4 additions & 32 deletions qubes-rpc/services/qvc.ScreenShare
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
#!/bin/bash
#!/bin/sh --

# Copyright (C) 2021 Elliot Killick <[email protected]>
# Copyright (C) 2021 Demi Marie Obenour <[email protected]>
# Licensed under the MIT License. See LICENSE file for details.

[ "$DEBUG" == 1 ] && set -x

set -E # Enable function inheritance of traps
trap exit ERR

export DISPLAY=":0"

first_connected_screen_input_dimensions="$(xrandr | grep -w "connected" | head -1 | cut -d '+' -f 1 | awk '{ print $NF }')"

width="$(echo "$first_connected_screen_input_dimensions" | awk -F x '{ print $1 }')"
height="$(echo "$first_connected_screen_input_dimensions" | awk -F x '{ print $2 }')"

fps="30"
frame_rate="$fps/1"

echo "$width $height $fps"

echo "Starting screen sharing at ${width}x${height} ${fps} FPS..." >&2

# shellcheck source=../../ui/ui.sh
source "/usr/share/qubes-video-companion/ui/ui.sh"
trap 'remove_ui $!' EXIT
create_ui screenshare

gst-launch-1.0 -q ximagesrc use-damage=false ! \
queue ! \
"video/x-raw,width=$width,height=$height,framerate=$frame_rate,format=BGRx" ! \
videoconvert ! \
"video/x-raw,format=I420" ! \
fdsink
export DISPLAY=:0
exec python3 -- /usr/share/qubes-video-companion/sender/screenshare.py
36 changes: 4 additions & 32 deletions qubes-rpc/services/qvc.Webcam
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
#!/bin/bash
#!/bin/sh --

# Copyright (C) 2021 Elliot Killick <[email protected]>
# Copyright (C) 2021 Demi Marie Obenour <[email protected]>
# Licensed under the MIT License. See LICENSE file for details.

[ "$DEBUG" == 1 ] && set -x

set -E # Enable function inheritance of traps
trap exit ERR

webcam_device="/dev/video0"
# This command exits with code 255 even though no error is reported
v4l2_webcam_info="$(v4l2-ctl -d "$webcam_device" --all)" || [ $? == 255 ]

dimensions="$(echo "$v4l2_webcam_info" | grep 'Width/Height' | awk '{ print $3 }')"
width="$(echo "$dimensions" | awk -F / '{ print $1 }')"
height="$(echo "$dimensions" | awk -F / '{ print $2 }')"

frame_rate="$(v4l2-ctl -d "$webcam_device" --all | grep 'Frames per second' | awk '{ print $5 }' | tr -d '()')"
fps="$(echo "$frame_rate" | awk -F / '{ print $1 }')" # Support a minimum of one frame per second

echo "$width $height $fps"

echo "Starting webcam stream at ${width}x${height} ${fps} FPS..." >&2

# shellcheck source=../../ui/ui.sh
source "/usr/share/qubes-video-companion/ui/ui.sh"
trap 'remove_ui $!' EXIT
create_ui webcam

gst-launch-1.0 -q v4l2src ! \
queue ! \
jpegdec ! \
"video/x-raw,width=$width,height=$height,framerate=$frame_rate" ! \
fdsink
export DISPLAY=:0
exec python3 -- /usr/share/qubes-video-companion/sender/webcam.py
File renamed without changes.
2 changes: 1 addition & 1 deletion video/destroy.sh → receiver/destroy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ set -E # Enable function inheritance of traps
trap exit ERR

# shellcheck source=common.sh
source /usr/share/qubes-video-companion/video/common.sh
source /usr/share/qubes-video-companion/receiver/common.sh

if ! test_v4l2loopback; then
exit 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ esac
exit_clean() {
exit_code="$?"

/usr/share/qubes-video-companion/video/destroy.sh
/usr/share/qubes-video-companion/receiver/destroy.sh
sudo rm -f "$qvc_lock_file"

if [ "$video_source" == "webcam" ] && [ "$exit_code" == "141" ]; then
Expand All @@ -50,7 +50,7 @@ else
exit 1
fi

/usr/share/qubes-video-companion/video/setup.sh
/usr/share/qubes-video-companion/receiver/setup.sh
# Disabling buffering should lower latency and it doesn't seem to impact performance
# Filter standard error escape characters for safe printing to the terminal from the video sender
qrexec-client-vm dom0 "$qvc_service" /usr/share/qubes-video-companion/video/receiver.sh --buffer-size=0 --filter-escape-chars-stderr
qrexec-client-vm --buffer-size=0 --filter-escape-chars-stderr -- dom0 "$qvc_service" /usr/share/qubes-video-companion/receiver/receiver.py
68 changes: 68 additions & 0 deletions receiver/receiver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/python3 --

# Copyright (C) 2021 Elliot Killick <[email protected]>
# Copyright (C) 2021 Demi Marie Obenour <[email protected]>
# Licensed under the MIT License. See LICENSE file for details.

import sys
import struct
import os
from typing import NoReturn

def main(argv) -> NoReturn:
if len(argv) != 1:
raise RuntimeError('should not have any arguments')

width, height, fps = read_video_parameters()

print('Receiving video stream at {}x{} {} FPS...'.format(width, height, fps),
file=sys.stderr)
os.execv('/usr/bin/gst-launch-1.0', (
'gst-launch-1.0',
'fdsrc',
'!',
'queue',
'!',
'capsfilter',
'caps=video/x-raw,'
'width={0},'
'height={1},'
'framerate={2}/1,'
'format=I420,'
'colorimetry=2:4:7:1,'
'chroma-site=none,'
'interlace-mode=progressive,'
'pixel-aspect-ratio=1/1,'
'max-framerate={2}/1,'
'views=1'.format(width, height, fps),
'!',
'rawvideoparse',
'use-sink-caps=true',
'!',
'v4l2sink',
'device=/dev/video0',
'sync=false',
))

def read_video_parameters() -> (int, int, int):
input_size = 6

s = struct.Struct('=HHH')
if s.size != input_size:
raise AssertionError('bug')

untrusted_input = os.read(0, input_size)
if len(untrusted_input) != input_size:
raise RuntimeError('wrong number of bytes read')
untrusted_width, untrusted_height, untrusted_fps = s.unpack(untrusted_input)
del untrusted_input

if untrusted_width > 4096 or untrusted_height > 4096 or untrusted_fps > 4096:
raise RuntimeError('excessive width, height, and/or fps')
width, height, fps = untrusted_width, untrusted_height, untrusted_fps
del untrusted_width, untrusted_height, untrusted_fps

return width, height, fps

if __name__ == '__main__':
main(sys.argv)
4 changes: 2 additions & 2 deletions video/setup.sh → receiver/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ set -E # Enable function inheritance of traps
trap exit ERR

# shellcheck source=common.sh
source /usr/share/qubes-video-companion/video/common.sh
source /usr/share/qubes-video-companion/receiver/common.sh

if ! test_v4l2loopback; then
echo "The v4l2loopback kernel module is not installed. Please run the following script to install it: /usr/share/qubes-video-companion/scripts/v4l2loopback/install.sh"
Expand All @@ -19,7 +19,7 @@ fi
# exclusive_caps=1: Some applications such as Cheese and Chromium won't detect the video device if it's set to zero
sudo modprobe v4l2loopback card_label="Qubes Video Companion" exclusive_caps=1

# For some reason, AppVMs based off my self-made "kali" qube (which itself is based off the "debian-10" TemplateVM) that are using the 5.x Qubes Linux kernel no longer hasthe user permitting ACL (or any ACL for that matter) on /dev/video* devices causing a permission error when attempting to write video to the device
# For some reason, AppVMs based off my self-made "kali" qube (which itself is based off the "debian-10" TemplateVM) that are using the 5.x Qubes Linux kernel no longer has the user permitting ACL (or any ACL for that matter) on /dev/video* devices causing a permission error when attempting to write video to the device
# As a workaround, we set the ACL ourselves in case it isn't already applied
# This issue does not occur on the Fedora or Debian AppVMs using the 5.x Qubes Linux kernel, more research is required
sudo setfacl -m user:user:rw /dev/video0
12 changes: 6 additions & 6 deletions rpm_spec/qubes-video-companion-dom0.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ make DESTDIR=%{?buildroot} install-dom0 install-license
%{_sysconfdir}/qubes-rpc/qvc.ScreenShare
%{_sysconfdir}/qubes-rpc/policy/qvc.Webcam
%{_sysconfdir}/qubes-rpc/policy/qvc.ScreenShare
%{_datadir}/qubes-video-companion/ui/ui.sh
%{_datadir}/qubes-video-companion/ui/main.py
%{_datadir}/qubes-video-companion/ui/user_interface.py
%{_datadir}/qubes-video-companion/ui/notification.py
%{_datadir}/qubes-video-companion/ui/tray_icon.py
%{_datadir}/qubes-video-companion/scripts/set-webcam-format.sh
%{_sysconfdir}/qubes/rpc-config/qvc.Webcam
%{_sysconfdir}/qubes/rpc-config/qvc.ScreenShare
%{_datadir}/qubes-video-companion/sender/service.py
%{_datadir}/qubes-video-companion/sender/webcam.py
%{_datadir}/qubes-video-companion/sender/screenshare.py
%{_datadir}/qubes-video-companion/sender/tray_icon.py

%changelog
* Wed Feb 17 2021 Elliot Killick <[email protected]> 1.0.0-1
Expand Down
25 changes: 13 additions & 12 deletions rpm_spec/qubes-video-companion.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ BuildArch: noarch

BuildRequires: pandoc
Requires: gstreamer1-plugins-good
Requires: python3

%description
Qubes Video Companion is a tool for securely streaming webcams and sharing
Expand All @@ -26,12 +27,12 @@ exposed. This design makes the side of the video sending virtual machine 100%
immune to attack and only leaves a very small attack surface on the side of
the video receiving virtual machine.

The project emphasizes correctness and security all the while also sporting
The project emphasizes correctness and security all thae while also sporting
superb performance by maintaining a small footprint of the available
computational resources and low latency even at Full HD and greater
resolutions at 30 or more frames per second.

This package contains all components of Qubes Video companion excluding the
This package contains all components of Qubes Video Companion excluding the
Qubes RPC policies which dom0 enforces.

%prep
Expand All @@ -53,16 +54,16 @@ make DESTDIR=%{?buildroot} install-vm install-license
%{_bindir}/qubes-video-companion
%{_sysconfdir}/qubes-rpc/qvc.Webcam
%{_sysconfdir}/qubes-rpc/qvc.ScreenShare
%{_datadir}/qubes-video-companion/video/setup.sh
%{_datadir}/qubes-video-companion/video/receiver.sh
%{_datadir}/qubes-video-companion/video/destroy.sh
%{_datadir}/qubes-video-companion/video/common.sh
%{_datadir}/qubes-video-companion/ui/ui.sh
%{_datadir}/qubes-video-companion/ui/main.py
%{_datadir}/qubes-video-companion/ui/user_interface.py
%{_datadir}/qubes-video-companion/ui/notification.py
%{_datadir}/qubes-video-companion/ui/tray_icon.py
%{_datadir}/qubes-video-companion/scripts/set-webcam-format.sh
%{_sysconfdir}/qubes/rpc-config/qvc.Webcam
%{_sysconfdir}/qubes/rpc-config/qvc.ScreenShare
%{_datadir}/qubes-video-companion/receiver/setup.sh
%{_datadir}/qubes-video-companion/receiver/receiver.py
%{_datadir}/qubes-video-companion/receiver/destroy.sh
%{_datadir}/qubes-video-companion/receiver/common.sh
%{_datadir}/qubes-video-companion/sender/service.py
%{_datadir}/qubes-video-companion/sender/webcam.py
%{_datadir}/qubes-video-companion/sender/screenshare.py
%{_datadir}/qubes-video-companion/sender/tray_icon.py
%{_datadir}/qubes-video-companion/scripts/webcam.html
%{_datadir}/qubes-video-companion/scripts/v4l2loopback/install.sh
%{_datadir}/qubes-video-companion/scripts/v4l2loopback/author.asc
Expand Down
Loading

0 comments on commit 4d276ff

Please sign in to comment.