Add native themed session locker and Settings integration
This commit is contained in:
1 parent
8eca921345
commit
f8b8704f8b
18 files changed
+1422
-19
No files matched your search
@@ -39,12 +39,24 @@ if [[ -e $session_entry ]]; then
|
||||
echo "Different session entry exists: $session_entry" >&2; exit 1;
|
||||
}
|
||||
fi
|
||||
for name in ferese ferese-shell ferese-settings feresectl; do
|
||||
for name in ferese ferese-shell ferese-settings feresectl ferese-lock; do
|
||||
[[ -x $repo_dir/target/release/$name ]] || { echo "Missing release binary: $name" >&2; exit 1; }
|
||||
done
|
||||
for name in ferese.png ferese.svg; do
|
||||
[[ -f $repo_dir/assets/wallpapers/$name ]] || { echo "Missing wallpaper asset: $name" >&2; exit 1; }
|
||||
done
|
||||
# Preserve administrator-supplied policies. New installs use the distro's
|
||||
# authentication and account stacks, never a permissive fallback.
|
||||
pam_policy=generic
|
||||
if [[ -f /etc/pam.d/system-auth ]]; then
|
||||
pam_policy=fedora
|
||||
elif [[ -f /etc/pam.d/common-auth && -f /etc/pam.d/common-account ]]; then
|
||||
pam_policy=debian
|
||||
elif [[ ! -f /etc/pam.d/login && ! -f /etc/pam.d/ferese-lock ]]; then
|
||||
echo 'No supported PAM stack found; install /etc/pam.d/ferese-lock first.' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
desktop-file-validate "$repo_dir/packaging/ferese.desktop"
|
||||
desktop-file-validate "$repo_dir/packaging/dev.ferese.Settings.desktop"
|
||||
|
||||
@@ -52,11 +64,10 @@ install -d -m 0755 -- "$release_dir" /usr/local/bin /usr/share/wayland-sessions
|
||||
if [[ -e $session_entry ]]; then
|
||||
install -m 0644 -- "$session_entry" "$release_dir/session.previous.desktop"
|
||||
fi
|
||||
for name in ferese ferese-shell ferese-settings feresectl; do
|
||||
for name in ferese ferese-shell ferese-settings feresectl ferese-lock; do
|
||||
install -m 0755 -- "$repo_dir/target/release/$name" "$release_dir/$name"
|
||||
done
|
||||
install -m 0755 -- "$repo_dir/packaging/ferese-session" "$release_dir/ferese-session"
|
||||
install -m 0755 -- "$repo_dir/packaging/ferese-lock" "$release_dir/ferese-lock"
|
||||
install -m 0755 -- "$repo_dir/packaging/ferese-screenshot" "$release_dir/ferese-screenshot"
|
||||
install -m 0644 -- "$repo_dir/packaging/config.kdl" "$release_dir/config.example.kdl"
|
||||
install -D -m 0644 -- "$repo_dir/assets/fonts/Comfortaa-LICENSE.txt" "$release_dir/licenses/Comfortaa-LICENSE.txt"
|
||||
@@ -65,6 +76,10 @@ install -d -m 0755 -- "$release_dir/wallpapers"
|
||||
install -m 0644 -- "$repo_dir/assets/wallpapers/ferese.png" "$release_dir/wallpapers/ferese.png"
|
||||
install -m 0644 -- "$repo_dir/assets/wallpapers/ferese.svg" "$release_dir/wallpapers/ferese.svg"
|
||||
|
||||
if [[ ! -e /etc/pam.d/ferese-lock ]]; then
|
||||
install -D -m 0644 -- "$repo_dir/packaging/pam.d/ferese-lock.$pam_policy" /etc/pam.d/ferese-lock
|
||||
fi
|
||||
|
||||
if [[ -L $install_root/current ]]; then
|
||||
ln -sfn -- "$(readlink -- "$install_root/current")" "$install_root/previous"
|
||||
fi
|
||||
@@ -78,4 +93,4 @@ install -D -m 0644 -- "$repo_dir/packaging/dev.ferese.Settings.desktop" /usr/loc
|
||||
install -D -m 0644 -- "$repo_dir/packaging/icons/ferese.svg" /usr/local/share/icons/hicolor/scalable/apps/dev.ferese.Settings.svg
|
||||
install -D -m 0644 -- "$repo_dir/packaging/icons/ferese.svg" /usr/local/share/icons/hicolor/scalable/apps/ferese.svg
|
||||
if command -v update-desktop-database >/dev/null; then update-desktop-database /usr/local/share/applications || true; fi
|
||||
echo "Installed Ferese $release_id. Select Ferese in SDDM."
|
||||
echo "Installed Ferese $release_id. Select Ferese at your login screen, or run /usr/local/bin/ferese-session from a local TTY."
|
||||
+3
-3
@@ -49,7 +49,7 @@ desktop-file-validate "$repo_dir/packaging/ferese.desktop"
|
||||
|
||||
build=(cargo build --manifest-path "$repo_dir/Cargo.toml"
|
||||
--target-dir "$repo_dir/target" --release --locked
|
||||
-p ferese -p ferese-shell -p ferese-settings -p feresectl)
|
||||
-p ferese -p ferese-shell -p ferese-settings -p feresectl -p ferese-lock)
|
||||
if $offline; then build+=(--offline); fi
|
||||
if ! $skip_build; then
|
||||
((EUID != 0)) || fail 'build as your normal user, without sudo (or use --skip-build)'
|
||||
@@ -75,8 +75,8 @@ fi
|
||||
|
||||
cd -- "$repo_dir"
|
||||
if ! $skip_build; then "${build[@]}"; fi
|
||||
for name in ferese ferese-shell ferese-settings feresectl; do
|
||||
for name in ferese ferese-shell ferese-settings feresectl ferese-lock; do
|
||||
[[ -x $repo_dir/target/release/$name ]] || fail "missing release binary: $name"
|
||||
done
|
||||
"${installer[@]}"
|
||||
echo 'Installation complete. Log out and select Ferese at the login screen.'
|
||||
echo 'Installation complete. Log out and select Ferese at your login screen, or run ferese-session from a local TTY.'
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Opt-in lock protocol smoke test. Opens a temporary nested compositor.
|
||||
Run: FERESE_TEST_LOCK=1 python3 scripts/tests/test_lock_isolated.py
|
||||
Requires release binaries, bwrap and grim. Host PAM is never modified.
|
||||
"""
|
||||
import os
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
@unittest.skipUnless(os.environ.get("FERESE_TEST_LOCK") == "1", "visible nested lock test is opt-in")
|
||||
class NativeLockTest(unittest.TestCase):
|
||||
def test_confirmation_capture_and_crash(self):
|
||||
import os, pathlib, signal, subprocess, tempfile, time
|
||||
os.chdir(Path(__file__).resolve().parents[2])
|
||||
root=pathlib.Path(tempfile.mkdtemp(prefix='ferese-lock-test-'))
|
||||
runtime=root/'runtime';runtime.mkdir(mode=0o700)
|
||||
config=root/'config'/'ferese';config.mkdir(parents=True)
|
||||
(config/'config.kdl').write_text('')
|
||||
pam=root/'pam';pam.mkdir()
|
||||
# Deny-only policy confined to a mount namespace; never changes host PAM.
|
||||
(pam/'ferese-lock').write_text('auth required pam_deny.so\naccount required pam_deny.so\n')
|
||||
host_display=os.environ.get('WAYLAND_DISPLAY','wayland-1')
|
||||
if not host_display.startswith('/'):host_display=str(pathlib.Path(os.environ['XDG_RUNTIME_DIR'])/host_display)
|
||||
env=dict(os.environ,XDG_RUNTIME_DIR=str(runtime),XDG_CONFIG_HOME=str(root/'config'),WAYLAND_DISPLAY=host_display,FERESE_ENABLE_SCREENCOPY='1')
|
||||
log=(root/'compositor.log').open('w')
|
||||
compositor=subprocess.Popen(['target/release/ferese','--backend','nested'],env=env,stdout=log,stderr=subprocess.STDOUT)
|
||||
locker=None
|
||||
locker_log=(root/'locker.log').open('w')
|
||||
try:
|
||||
for _ in range(100):
|
||||
if compositor.poll() is not None:raise RuntimeError('Nested compositor exited')
|
||||
sockets=[p for p in runtime.glob('wayland-*') if not p.name.endswith('.lock')]
|
||||
if sockets:break
|
||||
time.sleep(.1)
|
||||
childenv=dict(env,WAYLAND_DISPLAY=str(sockets[0]),FERESE_LOCK_READY='1')
|
||||
time.sleep(.6)
|
||||
subprocess.run(['grim',str(root/'unlocked.png')],env=childenv,check=True,timeout=10,capture_output=True)
|
||||
locker=subprocess.Popen(['bwrap','--bind','/','/','--dev-bind','/dev','/dev','--ro-bind',str(pam),'/etc/pam.d','--unshare-user','--','target/release/ferese-lock'],env=childenv,stdout=subprocess.DEVNULL,stderr=locker_log,start_new_session=True)
|
||||
assert locker.wait(timeout=20) == 0, (root/'locker.log').read_text()
|
||||
print('Native locker received compositor confirmation',flush=True)
|
||||
result=subprocess.run(['grim',str(root/'locked.png')],env=childenv,timeout=10,capture_output=True)
|
||||
assert result.returncode != 0, 'Capture unexpectedly succeeded during lock'
|
||||
print('Screencopy denied while native locker is running',flush=True)
|
||||
os.killpg(locker.pid, signal.SIGKILL)
|
||||
time.sleep(.3)
|
||||
result=subprocess.run(['grim',str(root/'after-crash.png')],env=childenv,timeout=10,capture_output=True)
|
||||
assert result.returncode != 0, 'Capture unexpectedly succeeded after locker crash'
|
||||
print('Screencopy remains denied after locker crash',flush=True)
|
||||
finally:
|
||||
if locker is not None:
|
||||
try: os.killpg(locker.pid, signal.SIGKILL)
|
||||
except ProcessLookupError: pass
|
||||
locker.wait()
|
||||
compositor.terminate()
|
||||
try:compositor.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:compositor.kill();compositor.wait()
|
||||
log.close()
|
||||
locker_log.close()
|
||||
print(root,flush=True)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user