From a37ffc3374e23b8e6318965d84e408acf7a46b73 Mon Sep 17 00:00:00 2001 From: Harald Kubota Date: Sat, 2 Jan 2021 15:32:15 +0900 Subject: Add first version of zsh completion Don't have duplicate descriptions and put = signs where they belong to zsh completion function now dynamically adjusts for options (e.g. no --apparmor option without AppArmor configured) No EXTRA_CFLAGS for cpp Found main.c which does the argument processing. Moved some arguments into the correct #ifdef blocks Profile selection now much better Not more cpp. Using preproc.awk instead. Updated bash firejail command completion to add profiles ignore bash and zsh dynamically created completion scripts Moved bash/zsh completions out of ALL_ITEMS to fix make install Cleanup --- src/zsh_completion/Makefile.in | 14 +++ src/zsh_completion/_firejail.in | 246 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 src/zsh_completion/Makefile.in create mode 100644 src/zsh_completion/_firejail.in (limited to 'src/zsh_completion') diff --git a/src/zsh_completion/Makefile.in b/src/zsh_completion/Makefile.in new file mode 100644 index 000000000..3f756aa5f --- /dev/null +++ b/src/zsh_completion/Makefile.in @@ -0,0 +1,14 @@ +all: _firejail + +include ../common.mk + +_firejail: _firejail.in + gawk -f ../man/preproc.awk -- $(MANFLAGS) < $< > $@.tmp + sed "s|_SYSCONFDIR_|$(sysconfdir)|" < $@.tmp > $@ + rm $@.tmp + +clean: + rm -fr _firejail + +distclean: clean + rm -fr Makefile diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in new file mode 100644 index 000000000..7e8df138e --- /dev/null +++ b/src/zsh_completion/_firejail.in @@ -0,0 +1,246 @@ +#compdef firejail + +_all_firejails() { + local -a _all_firejails_list + for jail in ${(f)"$(_call_program modules_tag "firejail --list 2> /dev/null | cut -d: -f1")"}; do + _all_firejails_list+=${jail%% *} + done + _describe 'firejails list' _all_firejails_list +} + +_all_cpus() { + _cpu_count=$(getconf _NPROCESSORS_ONLN) + for i in {0..$((_cpu_count-1))} ; do + print $i + done +} + +_profiles() { + print $1/*.profile | sed -E "s;^$1/;;g;s;\.profile$;;g;" +} +_profiles_with_ext() { + print $1/*.profile +} + +_all_profiles() { + _values 'profiles' $(_profiles _SYSCONFDIR_/firejail) $(_profiles $HOME/.config/firejail) $(_profiles_with_ext .) +} + +_firejail_args=( + '*::arguments:_normal' + '(--profile)'{--profile=,--profile=}'[use a custom profile]: :_all_profiles' + '--caps[enable default Linux capabilities filter]' + '(--caps.drop)'{--caps.drop=,--caps.drop=}'[drop capabilities: all|cap1,cap2,...]: :->caps_drop' + '(--caps.keep)'{--caps.keep=,--caps.keep=}'[keep capabilities: cap1,cap2,...]: :->caps_keep' + '(--caps.print)'{--caps.print=,--caps.print=}'[print the caps filter name|pid]:firejail:_all_firejails' + '--allow-debuggers[allow tools such as strace and gdb inside the sandbox]' + '(--debug)'{--debug,--debug}'[print sandbox debug messages]' + '--debug-blacklists[debug blacklisting]' + '--debug-caps[print all recognized capabilities]' + '--debug-errnos[print all recognized error numbers]' + '--debug-private-lib[debug for --private-lib option]' + '--debug-protocols[print all recognized protocols]' + '--debug-syscalls[print all recognized system calls]' + '--debug-syscalls32[print all recognized 32 bit system calls]' + '--debug-whitelists[debug whitelisting]' + # Ignore that you can do -? too as it's the only short option + '(--help)'{--help,--help}'[this help screen]' + '--allusers[all user home directories are visible inside the sandbox]' + '--appimage[sandbox an AppImage application]' + '--private[temporary home directory]' + '(--private)'{--private=,--private=}'[use directory as user home]: : _files -/' + '--seccomp[enable seccomp filter and apply the default blacklist]' + '(--seccomp=)'{--seccomp=,--seccomp=}'[enable seccomp filter, blacklist the default syscall list and the syscalls specified by the command]:' + '(--seccomp.print)'{--seccomp.print=,--seccomp.print=}'[print the seccomp filter for the sandbox identified by name|pid]: : _all_firejails' + '--seccomp.block-secondary[build only the native architecture filters]' + '(--seccomp.drop)'{--seccomp.drop=,--seccomp.drop=}'[enable seccomp filter, and blacklist the syscalls specified by the command]: :' + '(--seccomp.keep)'{--seccomp.keep=,--seccomp.keep=}'[enable seccomp filter, and whitelist the syscalls specified by the command]: :' + '(--seccomp.32.drop)'{--seccomp.32.drop=,--seccomp.32.drop=}'[enable seccomp filter, and blacklist the 32 bit syscalls specified by the command]: :' + '(--seccomp.32.keep)'{--seccomp.32.keep=,--seccomp.32.keep=}'[enable seccomp filter, and whitelist the 32 bit syscalls specified by the command]: :' + '(--seccomp-error-action)'{--seccomp-error-action=,--seccomp-error-action=}'[change error code, kill process or log the attempt]: :(ERRNO kill log)' + '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' + '*'{--blacklist=,--blacklist=}'[blacklist directory or file]: : _files' + '--writable-etc[/etc directory is mounted read-write]' + '--writable-run-user[allow access to /run/user/$UID/systemd and /run/user/$UID/gnupg]' + '--writable-var[/var directory is mounted read-write]' + '--writable-var-log[use the real /var/log directory, not a clone]' + '--build[build a whitelisted profile for the application and print it on stdout]' + '(--build)'{--build=,--build=}'[build a whitelisted profile for the application and save it]: : _files' + '(--fs.print)'{--fs.print=,--fs.print=}'[print the filesystem log name|pid]: : _all_firejails' + '(--join)'{--join=,--join=}'[join the sandbox name|pid]: : _all_firejails' + '(--join-filesystem)'{--join-filesystem=,--join-filesystem=}'[join the mount namespace name|pid]: : _all_firejails' + '(--profile.print)'{--profile.print=,--profile.print=}'[print the name of profile file name|pid]: : _all_firejails' + '(--protocol.print)'{--protocol.print=,--protocol.print=}'[print the protocol filter name|pid]: : _all_firejails' + '(--shutdown)'{--shutdown=,--shutdown=}'[shutdown the sandbox identified by name|pid]: : _all_firejails' + '(--cat)'{--cat=,--cat=}'[print content of file from sandbox container name|pid]: : _all_firejails' + '(--cpu.print)'{--cpu.print=,--cpu.print=}'[print the cpus in use name|pid]: : _all_firejails' + '--list[list all sandboxes]' + '(--dns)'{--dns=,--dns=}'[set DNS server]: :' + '(--protocol)'{--protocol=,--protocol=}'[enable protocol filter]: :' + '(--join-or-start)'{--join-or-start=,--join-or-start=}'[join the sandbox or start a new one name|pid]: : _all_firejails' + '(--hosts-file)'{--hosts-file=,--hosts-file=}'[use file as /etc/hosts]: : _files' + '--shell=none[run the program directly without a user shell]' + '(--shell)'{--shell=,--shell=}'[set default user shell]: : _files -g "*(*)"' + '(--output)'{--output=,--output=}'[stdout logging and log rotation]: : _files' + '(--output-stderr)'{--output-stderr=,--output-stderr=}'[stdout and stderr logging and log rotation]: : _files' + '--no3d[disable 3D hardware acceleration]' + '--nodvd[disable DVD and audio CD devices]' + '--nogroups[disable supplementary groups]' + '--nonewprivs[sets the NO_NEW_PRIVS prctl]' + '--noprofile[do not use a security profile]' + '(--noexec)'{--noexec=,--noexec=}'[remount the file or directory noexec nosuid and nodev]: : _files' + '--ipc-namespace[enable a new IPC namespace]' + '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]' + '--keep-var-tmp[/var/tmp directory is untouched]' + '--top[monitor the most CPU-intensive sandboxes]' + '--trace[trace open, access and connect system calls]' + '--tracelog[add a syslog message for every access to files or directories blacklisted by the security profile]' + '--tree[print a tree of all sandboxed processes]' + '(--cpu)'{--cpu=,--cpu=}'[set cpu affinity]: :->cpus' + '--private-dev[create a new /dev directory with a small number of common device files]' + '--private-tmp[mount a tmpfs on top of /tmp directory]' + '--private-cwd[do not inherit working directory inside jail]' + '(--private-cwd)'{--private-cwd=,--private-cwd=}'[set working directory inside jail]: : _files -/' + '*'{--read-only=,--read-only=}'[set directory or file read-only]: : _files' + '*'{--read-write=,--read-write=}'[set directory or file read-write]: : _files' + '(--tmpfs)'{--tmpfs=,--tmpfs=}'[mount a tmpfs filesystem on directory dirname]: : _files -/' + '(--private-etc)'{--private-etc=,--private-etc=}'[build a new /etc in a temporary filesystem, and copy the files and directories in the list]: : _files' + "--deterministic-exit-code[always exit with first child's status code]" + '--machine-id[preserve /etc/machine-id]' + # Sample values as I don't think + # many would enjoy getting a list from -20..20 + '(--nice)'{--nice=,--nice=}'[set nice value]: :(1 10 15 20)' + # Should be _files, a comma and files or files -/ + '*'{--bind=,--bind=}'[mount-bind dirname1/filename1 on top of dirname2/filename2]: :(file1,file2 dir1,dir2)' + '--audit[audit the sandbox]' + '(--audit)'{--audit=,--audit=}'[audit the sandbox with a test-program]: :' + '(--cgroup)'{--cgroup=,--cgroup=}'[place the sandbox in the specified control group]: :' + '*'{--env=,--env=}'[set environment variable]: :' + '(--hostname)'{--hostname=,--hostname=}'[set sandbox hostname]: :' + '(--ignore)'{--ignore=,--ignore=}'[ignore command in profile files]: :' + '(--name)'{--name=,--name=}'[set sandbox name]: :' + '(--rlimit-as)'{--rlimit-as=,--rlimit-as=}"[set the maximum size of the process's virtual memory (address space) in bytes]: :" + '(--rlimit-cpu)'{--rlimit-cpu=,--rlimit-cpu=}'[set the maximum CPU time in seconds]: :' + '(--rlimit-fsize)'{--rlimit-fsize=,--rlimit-fsize=}'[set the maximum file size that can be created by a process]: :' + '(--rlimit-nofile)'{--rlimit-nofile=,--rlimit-nofile=}'[set the maximum number of files that can be opened by a process]: :' + '(--rlimit-nproc)'{--rlimit-nproc=,--rlimit-nproc=}'[set the maximum number of processes that can be created for the real user ID of the calling process]: :' + '(--rlimit-sigpending)'{--rlimit-sigpending=,--rlimit-sigpending=}'[set the maximum number of pending signals for a process]: :' + '*'{--rmenv=,--rmenv=}'[remove environment variable in the new sandbox]: :' + '(--timeout)'{--timeout=,--timeout=}'[kill the sandbox automatically after the time has elapsed]: :(hh\:mm\:ss)' + "--quiet[turn off Firejail's output.]" + '--version[print program version and exit]' +#ifdef HAVE_APPARMOR + '--apparmor[enable AppArmor confinement]' + '(--apparmor.print=)'{--apparmor.print=,--apparmor.print=}'[print apparmor status name|pid]:firejail:_all_firejails' +#endif +#ifdef HAVE_CHROOT + '(--chroot)'{--chroot=,--chroot=}'[chroot into directory]: : _files -/' +#endif +#ifdef HAVE_FILE_TRANSFER + '(--get)'{--get=,--get=}'[get a file from sandbox container name|pid]: : _all_firejails' + # --put=name|pid src-filename dest-filename - put a file in sandbox container. + '(--put)'{--put=,--put=}'[put a file in sandbox container]: :' + '(--ls)'{--ls=,--ls=}'[list files in sandbox container name|pid]: : _all_firejails' +#endif +#ifdef HAVE_NETWORK + # '--net=none[enable a new, unconnected network namespace]' + '(--net)'{--net=,--net=}'[enable network namespaces and connect to this bridge or Ethernet interface (or none to disable)]: :->net_or_none' + '(--net.print)'{--net.print=,--net.print=}'[print network interface configuration name|pid]: : _all_firejails' + '(--netfilter.print)'{--netfilter.print=,--netfilter.print=}'[print the firewall name|pid]: : _all_firejails' + '(--netfilter6.print)'{--netfilter6.print=,--netfilter6.print=}'[print the IPv6 firewall name|pid]: : _all_firejails' + '--netstats[monitor network statistics]' + '(--netmask)'{--netmask=,--netmask=}'[define a network mask when dealing with unconfigured parrent interfaces]: :' + '(--netns)'{--netns=,--netns=}'[Run the program in a named, persistent network namespace]: :' + '(--netfilter)'{--netfilter=,--netfilter=}'[enable firewall]: :' + '(--netfilter6)'{--netfilter6=,--netfilter6=}'[enable IPv6 firewall]: :' + '(--veth-name)'{--veth-name=,--veth-name=}'[use this name for the interface connected to the bridge]: :' + '(--join-network)'{--join-network=,--join-network=}'[join the network namespace name|pid]: : _all_firejails' + '(--defaultgw)'{--defaultgw=,--defaultgw=}'[configure default gateway]: :' + '(--ip)'{--ip=,--ip=}'[set interface IP address none|dhcp|ADDRESS]: :(none dhcp)' + '(--dns.print)'{--dns.print=,--dns.print=}'[print DNS configuration name|pid]: : _all_firejails' + '(--interface)'{--interface=,--interface=}'[move interface in sandbox]: :' + '(--ip6)'{--ip6=,--ip6=}'[set interface IPv6 address or use dhcp via dhclient]: :(dhcp)' + '(--iprange)'{--iprange=,--iprange=}'[configure an IP address in this range]: :' + '(--mac)'{--mac=,--mac=}'[set interface MAC address]: :(xx\:xx\:xx\:xx\:xx\:xx)' + '(--mtu)'{--mtu=,--mtu=}'[set interface MTU]: :' + '--scan[ARP-scan all the networks from inside a network namespace]' + '(--bandwidth)'{--bandwidth=,--bandwidth=}'[set bandwidth limits name|pid]: : _all_firejails' +#endif +#ifdef HAVE_X11 + '--x11[enable X11 sandboxing. The software checks first if Xpra is installed, then it checks if Xephyr is installed. If all fails, it will attempt to use X11 security extension]' + '(--x11)'{--x11=,--x11=}'[disable or enable specific X11 server]: :(none xephyr xorg xpra xvfb)' + '(--xephyr-screen)'{--xephyr-screen=,--xephyr-screen=}'[set screen size for --x11=xephyr]: :(WIDTHxHEIGHT)' +#endif +#ifdef HAVE_USERNS + '--noroot[install a user namespace with only the current user]' +#endif + '--nosound[disable sound system]' + '--noautopulse[disable automatic ~/.config/pulse init]' + '--novideo[disable video devices]' + '--nou2f[disable U2F devices]' +#ifdef HAVE_OVERLAYFS + '--overlay[mount a filesystem overlay on top of the current filesystem]' + '(--overlay-named)'{--overlay-named=,--overlay-named=}'[mount a filesystem overlay on top of the current filesystem, and store it in name directory]: : _files -/' + '--overlay-tmpfs[mount a temporary filesystem overlay on top of the current filesystem]' + '--overlay-clean[clean all overlays stored in $HOME/.firejail directory]' +#endif +#ifdef HAVE_WHITELIST + '(--nowhitelist)'{--nowhitelist=,--nowhitelist=}'[disable whitelist for file or directory]: : _files' + '*'{--whitelist=,--whitelist=}'[whitelist directory or file]: : _files' +#endif + '(--noblacklist)'{--noblacklist=,--noblacklist=}'[disable blacklist for file or directory]: : _files' +#ifdef HAVE_DBUSPROXY + '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy or none]: :' + '(--dbus-system.broadcast)'{--dbus-system.broadcast=,--dbus-system.broadcast=}'[allow signals on the system DBus according to rule]: :' + '(--dbus-system.call)'{--dbus-system.call=,--dbus-system.call=}'[allow calls on the system DBus according to rule]: :' + '(--dbus-system.own)'{--dbus-system.own=,--dbus-system.own=}'[allow ownership of name on the system DBus]: :' + '(--dbus-system.see)'{--dbus-system.see=,--dbus-system.see=}'[allow seeing name on the system DBus]: :' + '(--dbus-system.talk)'{--dbus-system.talk=,--dbus-system.talk=}'[allow talking to name on the system DBus]: :' + '(--dbus-user)'{--dbus-user=,--dbus-user=}'[set session DBus access policy or none]: :' + '(--dbus-user.broadcast)'{--dbus-user.broadcast=,--dbus-user.broadcast=}'[allow signals on the session DBus according to rule]: :' + '(--dbus-user.call)'{--dbus-user.call=,--dbus-user.call=}'[allow calls on the session DBus according to rule]: :' + '(--dbus-user.see)'{--dbus-user.see=,--dbus-user.see=}'[allow seeing name on the session DBus]: :' + '(--dbus-user.talk)'{--dbus-user.talk=,--dbus-user.talk=}'[allow talking to name on the session DBus]: :' + '(--dbus-log)'{--dbus-log=,--dbus-log=}'[set DBus log file location]: : _files' + '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy]: :(filter none)' + '--dbus-user.log[turn on logging for the user DBus]' + '(--dbus-user.own)'{--dbus-user.own=,--dbus-user.own=}'[allow ownership of name on the session DBus]: :' + '--dbus-system.log[turn on logging for the system DBus]' + '--nodbus[disable D-Bus access]' +#endif +#ifdef HAVE_PRIVATE_HOME + '(--private-home)'{--private-home=,--private-home=}'[build a new user home in a temporary filesystem, and copy the files and directories in the list in the new home]: :' +#endif + '(--private-bin)'{--private-bin=,--private-bin=}'[build a new /bin in a temporary filesystem, and copy the programs in the list]: :' + '(--private-opt)'{--private-opt=,--private-opt=}'[build a new /opt in a temporary filesystem]: :' + '(--private-srv)'{--private-srv=,--private-srv=}'[build a new /srv in a temporary filesystem]: :' +#ifdef HAVE_USERTMPFS + '--private-cache[temporary ~/.cache directory]' +#endif +#ifdef HAVE_FIRETUNNEL + '(--tunnel)'{--tunnel=,--tunnel=}'[connect the sandbox to a tunnel created by firetunnel utility]: :' +#endif + ) + + +_firejail() { + _arguments -S $_firejail_args + case "$state" in + caps_drop) + local caps_and_all=(all $(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}')) + _values -s "," 'caps_drop' $caps_and_all + ;; + caps_keep) + local caps=($(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}')) + _values -s "," 'caps_keep' $caps + ;; + cpus) + _values -s "," 'cpus' $(_all_cpus) + ;; + net_or_none) + local netdevs=($(ip link | awk '{print $2}' | grep '^.*:$' | tr -d ':')) + local net_and_none=(none $netdevs) + _values 'net' $net_and_none + ;; + esac +} -- cgit v1.2.3-54-g00ecf