mirror of
https://github.com/Kicksecure/security-misc.git
synced 2025-05-02 11:16:06 -04:00
lintian FHS
This commit is contained in:
parent
6607c1e4bd
commit
4fadaad8c0
16 changed files with 0 additions and 0 deletions
|
@ -1,32 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
sigterm_trap() {
|
||||
if [ "$lastpid" = "" ]; then
|
||||
exit 143
|
||||
fi
|
||||
ps -p "$lastpid" >/dev/null 2>&1
|
||||
if [ ! "$?" = "0" ]; then
|
||||
## Already terminated.
|
||||
exit 143
|
||||
fi
|
||||
kill -s sigterm "$lastpid"
|
||||
exit 143
|
||||
}
|
||||
|
||||
trap "sigterm_trap" SIGTERM SIGINT
|
||||
|
||||
[ -n "$timeout_after" ] || timeout_after="600"
|
||||
[ -n "$kill_after" ] || kill_after="10"
|
||||
|
||||
timeout \
|
||||
--kill-after="$kill_after" \
|
||||
"$timeout_after" \
|
||||
apt-get update --error-on=any "$@" &
|
||||
|
||||
lastpid="$!"
|
||||
wait "$lastpid"
|
||||
|
||||
exit "$?"
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
set -x
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
wc -L "/var/lib/apt/lists/"*InRelease
|
||||
wc -L "/var/lib/apt/lists/"*InRelease | awk '$1 > 1024 {print; exit 1}'
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
set -e
|
||||
|
||||
title="$0: password required for $(whoami) to perform action as superuser"
|
||||
|
||||
zenity --password --title="$title"
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
set -e
|
||||
|
||||
echo "$PATH"
|
|
@ -1,96 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
set -e
|
||||
|
||||
sysfs_whitelist=1
|
||||
cpuinfo_whitelist=1
|
||||
|
||||
## https://www.whonix.org/wiki/Security-misc#selinux
|
||||
selinux=1
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
## Allows for disabling the whitelist.
|
||||
for i in /etc/hide-hardware-info.d/*.conf
|
||||
do
|
||||
bash -n "${i}"
|
||||
source "${i}"
|
||||
done
|
||||
|
||||
create_whitelist() {
|
||||
if [ "${1}" = "sysfs" ]; then
|
||||
whitelist_path="/sys"
|
||||
elif [ "${1}" = "cpuinfo" ]; then
|
||||
whitelist_path="/proc/cpuinfo"
|
||||
else
|
||||
echo "ERROR: ${1} is not a correct parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -q "${1}" /etc/group; then
|
||||
## Changing the permissions of /sys recursively
|
||||
## causes errors as the permissions of /sys/kernel/debug
|
||||
## and /sys/fs/cgroup cannot be changed.
|
||||
chgrp -fR "${1}" "${whitelist_path}" || true
|
||||
|
||||
chmod o-rwx "${whitelist_path}"
|
||||
else
|
||||
echo "ERROR: The ${1} group does not exist, the ${1} whitelist was not created."
|
||||
fi
|
||||
}
|
||||
|
||||
## sysfs and debugfs expose a lot of information
|
||||
## that should not be accessible by an unprivileged
|
||||
## user which includes hardware info, debug info and
|
||||
## more. This restricts /sys, /proc/cpuinfo, /proc/bus
|
||||
## and /proc/scsi to the root user only. This hides
|
||||
## many hardware identifiers from ordinary users
|
||||
## and increases security.
|
||||
for i in /proc/cpuinfo /proc/bus /proc/scsi /sys
|
||||
do
|
||||
if [ -e "${i}" ]; then
|
||||
if [ "${i}" = "/sys" ]; then
|
||||
## Whitelist for /sys.
|
||||
if [ "${sysfs_whitelist}" = "1" ]; then
|
||||
create_whitelist sysfs
|
||||
else
|
||||
chmod og-rwx /sys
|
||||
echo "INFO: The sysfs whitelist is not enabled. Some things may not work properly."
|
||||
fi
|
||||
elif [ "${i}" = "/proc/cpuinfo" ]; then
|
||||
## Whitelist for /proc/cpuinfo.
|
||||
if [ "${cpuinfo_whitelist}" = "1" ]; then
|
||||
create_whitelist cpuinfo
|
||||
else
|
||||
chmod og-rwx /proc/cpuinfo
|
||||
echo "INFO: The cpuinfo whitelist is not enabled. Some things may not work properly."
|
||||
fi
|
||||
else
|
||||
chmod og-rwx "${i}"
|
||||
fi
|
||||
else
|
||||
## /proc/scsi doesn't exist on Debian so errors
|
||||
## are expected here.
|
||||
if ! [ "${i}" = "/proc/scsi" ]; then
|
||||
echo "ERROR: ${i} could not be found."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
## https://www.whonix.org/wiki/Security-misc#selinux
|
||||
##
|
||||
## on SELinux systems, at least /sys/fs/selinux
|
||||
## must be visible to unprivileged users, else
|
||||
## SELinux userspace utilities will not function
|
||||
## properly
|
||||
if [ -d /sys/fs/selinux ]; then
|
||||
if [ "${selinux}" = "1" ]; then
|
||||
chmod o+rx /sys /sys/fs /sys/fs/selinux
|
||||
echo "INFO: SELinux mode enabled. Restrictions loosened slightly in order to allow userspace utilities to function."
|
||||
else
|
||||
echo "INFO: SELinux detected, but SELinux mode is not enabled. Some userspace utilities may not work properly."
|
||||
fi
|
||||
fi
|
|
@ -1,47 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## This is only a usability feature to avoid needlessly bumping pam_tally2
|
||||
## counter. This is not a security feature.
|
||||
## https://forums.whonix.org/t/restrict-root-access/7658/1
|
||||
|
||||
passwd_bin="$(type -P "passwd")"
|
||||
|
||||
if ! test -x "$passwd_bin" ; then
|
||||
echo "\
|
||||
$0: ERROR: passwd_bin \"$passwd_bin\" is not executable.
|
||||
See https://www.whonix.org/wiki/SUID_Disabler_and_Permission_Hardener#passwd" >&2
|
||||
## Identifiable exit codes in case stdout / stderr is not logged in journal.
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! passwd_output="$("$passwd_bin" -S "$PAM_USER" 2>/dev/null)" ; then
|
||||
echo "$0: ERROR: user \"$PAM_USER\" does not exist." >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if [ "$(echo "$passwd_output" | cut -d ' ' -f 2)" = "P" ]; then
|
||||
true "INFO: Password not locked."
|
||||
else
|
||||
echo "$0: INFO: Password for user \"$PAM_USER\" is locked."
|
||||
|
||||
if [ -f /usr/share/whonix/marker ] || [ -f /usr/share/kicksecure/marker ]; then
|
||||
if [ "$PAM_USER" = "root" ]; then
|
||||
echo "$0: ERROR: root account is locked by default. See:" >&2
|
||||
echo "https://www.whonix.org/wiki/root" >&2
|
||||
echo "" >&2
|
||||
exit 4
|
||||
fi
|
||||
fi
|
||||
|
||||
## Should not unconditionally 'exit 1' here.
|
||||
## Locked user accounts might have valid sudoers exceptions.
|
||||
## https://forums.whonix.org/t/pam-abort-on-locked-password-and-running-privileged-command-from-web-browser/10521
|
||||
## 'exit 1' would be good for usability here because then the user would get
|
||||
## faster feedback. A new login attempt would not be needlessly delayed.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -1,21 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## https://serverfault.com/questions/134471/success-n-control-syntax-in-pam-conf-pam-d-files
|
||||
|
||||
set -x
|
||||
|
||||
true "PAM_SERVICE: $PAM_SERVICE"
|
||||
|
||||
if [ "$PAM_SERVICE" = "login" ]; then
|
||||
## FIXME:
|
||||
## Creates unwanted journal log entry.
|
||||
## pam_exec(login:account): /usr/lib/security-misc/pam_only_if_login failed: exit code 1
|
||||
exit 1
|
||||
else
|
||||
## exit success so [success=1 default=ignore] will result in skipping the
|
||||
## next pam module.
|
||||
exit 0
|
||||
fi
|
|
@ -1,153 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
grep_result="$(grep "accessfile=/etc/security/access-security-misc.conf" /etc/pam.d/common-account 2>/dev/null)"
|
||||
|
||||
## Check if grep matched something.
|
||||
if [ ! "$grep_result" = "" ]; then
|
||||
## Yes, grep matched.
|
||||
|
||||
## Check if not out commented.
|
||||
if ! echo "$grep_result" | grep -q "#" ; then
|
||||
## Not out commented indeed.
|
||||
|
||||
## https://forums.whonix.org/t/etc-security-hardening-console-lockdown/8592
|
||||
|
||||
if id --name --groups --zero "$PAM_USER" | grep --quiet --null-data --line-regexp --fixed-strings "console"; then
|
||||
console_allowed=true
|
||||
fi
|
||||
if id --name --groups --zero "$PAM_USER" | grep --quiet --null-data --line-regexp --fixed-strings "console-unrestricted"; then
|
||||
console_allowed=true
|
||||
fi
|
||||
|
||||
if [ ! "$console_allowed" = "true" ]; then
|
||||
echo "$0: ERROR: PAM_USER: '$PAM_USER' is not a member of group 'console'" >&2
|
||||
echo "$0: To unlock, run the following command as superuser:" >&2
|
||||
echo "$0: (If you still have a sudo/root shell somewhere.)" >&2
|
||||
echo "" >&2
|
||||
echo "addgroup $PAM_USER console" >&2
|
||||
echo "" >&2
|
||||
echo "$0: However, possibly unlock procedure is required." >&2
|
||||
echo "$0: First boot into recovery mode at grub boot menu and then run above command." >&2
|
||||
echo "$0: See also:" >&2
|
||||
echo "https://www.whonix.org/wiki/root#console" >&2
|
||||
echo "" >&2
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
## https://forums.whonix.org/t/how-strong-do-linux-user-account-passwords-have-to-be-when-using-full-disk-encryption-fde-too/7698
|
||||
|
||||
if [ ! "$(id -u)" = "0" ]; then
|
||||
## as user "user"
|
||||
## /sbin/pam_tally2 -u user
|
||||
## pam_tally2: Error opening /var/log/tallylog for update: Permission denied
|
||||
## /sbin/pam_tally2: Authentication error
|
||||
##
|
||||
## xscreensaver runs as user "user", therefore pam_tally2 cannot function.
|
||||
## xscreensaver has its own failed login counter.
|
||||
##
|
||||
## https://askubuntu.com/questions/983183/how-lock-the-unlock-screen-after-wrong-password-attempts
|
||||
##
|
||||
## https://www.whonix.org/pipermail/whonix-devel/2019-September/001439.html
|
||||
true "$0: not started as root, exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
## Does not work (yet) for login, pam_securetty runs before and aborts.
|
||||
## Also this should only run for login since securetty covers only login.
|
||||
# if [ "$PAM_USER" = "root" ]; then
|
||||
# if [ -f /etc/securetty ]; then
|
||||
# grep_result="$(grep "^[^#]" /etc/securetty)"
|
||||
# if [ "$grep_result" = "" ]; then
|
||||
# echo "$0: ERROR: Root login is disabled." >&2
|
||||
# echo "$0: ERROR: This is because /etc/securetty is empty." >&2
|
||||
# echo "$0: See also:" >&2
|
||||
# echo "https://www.whonix.org/wiki/root#login" >&2
|
||||
# echo "" >&2
|
||||
# exit 0
|
||||
# fi
|
||||
# fi
|
||||
# fi
|
||||
|
||||
## Using || true to not break read-only disk boot without ro-mode-init or grub-live.
|
||||
pam_tally2_output="$(pam_tally2 --user "$PAM_USER")" || true
|
||||
|
||||
if [ "$pam_tally2_output" = "" ]; then
|
||||
true "$0: no failed login"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
## Example:
|
||||
#Login Failures Latest failure From
|
||||
#user 0
|
||||
|
||||
pam_tally2_output_last_line="$(echo "$pam_tally2_output" | tail -1)"
|
||||
## Example:
|
||||
#user 0
|
||||
|
||||
arr=($pam_tally2_output_last_line)
|
||||
user_name="${arr[0]}"
|
||||
failed_login_counter="${arr[1]}"
|
||||
|
||||
if [ ! "$PAM_USER" = "$user_name" ]; then
|
||||
echo "$0: ERROR: PAM_USER: '$PAM_USER' does not equal user_name: '$user_name'." >&2
|
||||
echo "$0: ERROR: Please report this bug." >&2
|
||||
echo "" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$failed_login_counter" = "0" ]; then
|
||||
true "$0: INFO: Failed login counter is 0, ok."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
deny_line="$(cat /etc/pam.d/common-auth | grep deny=)"
|
||||
## Example:
|
||||
#auth requisite pam_tally2.so even_deny_root deny=50 onerr=fail audit debug
|
||||
|
||||
for word in $deny_line ; do
|
||||
if echo "$word" | grep -q "deny=" ; then
|
||||
deny="$(echo "$word" | cut -d "=" -f 2)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$deny" == *[!0-9]* ]]; then
|
||||
echo "$0: ERROR: deny is not numeric." >&2
|
||||
echo "$0: ERROR: Please report this bug." >&2
|
||||
echo "" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
remaining_attempts="$(( $deny - $failed_login_counter ))"
|
||||
|
||||
if [ "$remaining_attempts" -le "0" ]; then
|
||||
echo "$0: ERROR: Login blocked after $failed_login_counter attempts." >&2
|
||||
echo "$0: To unlock, run the following command as superuser:" >&2
|
||||
echo "$0: (If you still have a sudo/root shell somewhere.)" >&2
|
||||
echo "" >&2
|
||||
echo "pam_tally2 --quiet -r --user $PAM_USER" >&2
|
||||
echo "" >&2
|
||||
echo "$0: However, most likely unlock procedure is required." >&2
|
||||
echo "$0: First boot into recovery mode at grub boot menu and then run above command." >&2
|
||||
echo "$0: See also:" >&2
|
||||
echo "https://www.whonix.org/wiki/root#unlock" >&2
|
||||
echo "" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "$0: WARNING: $failed_login_counter failed login attempts." >&2
|
||||
echo "$0: Login will be blocked after $deny attempts." >&2
|
||||
echo "$0: You have $remaining_attempts more attempts before unlock procedure is required." >&2
|
||||
echo "" >&2
|
||||
|
||||
if [ "$PAM_SERVICE" = "su" ]; then
|
||||
echo "$0: NOTE: Type the password. When entering the password, no password feedback (no asterisk (\"*\") symbol) will be shown." >&2
|
||||
echo "" >&2
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -1,42 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## https://serverfault.com/questions/134471/success-n-control-syntax-in-pam-conf-pam-d-files
|
||||
|
||||
set -x
|
||||
|
||||
true "PAM_SERVICE: $PAM_SERVICE"
|
||||
|
||||
## PAM configuration notes
|
||||
##
|
||||
## success=$num
|
||||
## "will specify how many rules to skip when successful."
|
||||
## https://serverfault.com/questions/134471/success-n-control-syntax-in-pam-conf-pam-d-files
|
||||
##
|
||||
## ignore
|
||||
## "when used with a stack of modules, the module's return status will not contribute to the return code the application obtains."
|
||||
## http://www.linux-pam.org/Linux-PAM-html/sag-configuration-file.html
|
||||
|
||||
## - Failed dovecot logins should not result in account getting locked.
|
||||
## - Failed SSH public key authentication attempts do not increase pam_tally2
|
||||
## counter for some reason.
|
||||
## This list can later be extended as needed.
|
||||
pam_service_exclusion_list="dovecot"
|
||||
|
||||
for pam_service_exclusion_item in $pam_service_exclusion_list ; do
|
||||
if [ "$PAM_SERVICE" = "$pam_service_exclusion_item" ]; then
|
||||
## exit success so [success=1 default=ignore] will result in skipping the
|
||||
## next PAM module (the pam_tally2 module).
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
## exit failure so [success=1 default=ignore] will result in running the
|
||||
## next PAM module (the pam_tally2 module).
|
||||
##
|
||||
## Causes confusing error message:
|
||||
## pam_exec(sudo:auth): /usr/lib/security-misc/pam_tally2_not_if_x failed: exit code 1
|
||||
## https://github.com/linux-pam/linux-pam/issues/329
|
||||
exit 1
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
set -e
|
||||
|
||||
if [ -f /usr/libexec/helper-scripts/pre.bsh ]; then
|
||||
## pre.bsh would `source` the following folders:
|
||||
## /etc/panic-on-oops_pre.d/*.conf
|
||||
## /usr/local/etc/panic-on-oops_pre.d/*.conf
|
||||
source /usr/libexec/helper-scripts/pre.bsh
|
||||
fi
|
||||
|
||||
## Makes the kernel panic on oopses. This prevents the kernel
|
||||
## from continuing to run a flawed processes. Many kernel exploits
|
||||
## will also cause an oops which this will make the kernel kill.
|
||||
sysctl kernel.panic_on_oops=1
|
|
@ -1,478 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706
|
||||
## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707
|
||||
|
||||
## To view previous modes and how these were changed:
|
||||
## meld /var/lib/permission-hardening/existing_mode/statoverride /var/lib/permission-hardening/new_mode/statoverride
|
||||
|
||||
## To undo:
|
||||
## sudo /usr/lib/security-misc/permission-hardening-undo
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
exit_code=0
|
||||
|
||||
mkdir -p /var/lib/permission-hardening/existing_mode
|
||||
mkdir -p /var/lib/permission-hardening/new_mode
|
||||
dpkg_admindir_parameter_existing_mode="--admindir /var/lib/permission-hardening/existing_mode"
|
||||
dpkg_admindir_parameter_new_mode="--admindir /var/lib/permission-hardening/new_mode"
|
||||
|
||||
echo_wrapper_ignore() {
|
||||
echo "run: $@"
|
||||
"$@" 2>/dev/null || true
|
||||
}
|
||||
|
||||
echo_wrapper_silent_ignore() {
|
||||
#echo "run: $@"
|
||||
"$@" 2>/dev/null || true
|
||||
}
|
||||
|
||||
echo_wrapper_audit() {
|
||||
echo "run: $@"
|
||||
return_code=0
|
||||
"$@" || \
|
||||
{ \
|
||||
return_code="$?" ; \
|
||||
exit_code=203 ; \
|
||||
echo "ERROR: above command failed with exit code '$return_code'! calling function name: '${FUNCNAME[1]}'" >&2 ; \
|
||||
};
|
||||
}
|
||||
|
||||
echo_wrapper_silent_audit() {
|
||||
#echo "run (debugging): $@"
|
||||
return_code=0
|
||||
"$@" || \
|
||||
{ \
|
||||
return_code="$?" ; \
|
||||
exit_code=204 ; \
|
||||
echo "ERROR: above command '$@' failed with exit code '$return_code'! calling function name: '${FUNCNAME[1]}'" >&2 ; \
|
||||
};
|
||||
}
|
||||
|
||||
sanity_tests() {
|
||||
echo_wrapper_silent_audit which \
|
||||
capsh getcap setcap stat find dpkg-statoverride getent xargs grep 1>/dev/null
|
||||
}
|
||||
|
||||
add_nosuid_statoverride_entry() {
|
||||
local fso_to_process
|
||||
fso_to_process="$fso"
|
||||
local should_be_counter
|
||||
should_be_counter="$(find "$fso_to_process" -perm /u=s,g=s | wc -l)" || true
|
||||
local counter_actual
|
||||
counter_actual=0
|
||||
|
||||
local line
|
||||
while read -r line; do
|
||||
true "line: $line"
|
||||
counter_actual="$(( counter_actual + 1 ))"
|
||||
|
||||
local arr file_name existing_mode existing_owner existing_group
|
||||
arr=($line)
|
||||
file_name="${arr[0]}"
|
||||
existing_mode="${arr[1]}"
|
||||
existing_owner="${arr[2]}"
|
||||
existing_group="${arr[3]}"
|
||||
|
||||
if [ "$arr" = "" ]; then
|
||||
echo "ERROR: arr is empty. line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$file_name" = "" ]; then
|
||||
echo "ERROR: file_name is empty. line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_mode" = "" ]; then
|
||||
echo "ERROR: existing_mode is empty. line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_owner" = "" ]; then
|
||||
echo "ERROR: existing_owner is empty. line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_group" = "" ]; then
|
||||
echo "ERROR: existing_group is empty. line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
## -h file True if file is a symbolic Link.
|
||||
## -u file True if file has its set-user-id bit set.
|
||||
## -g file True if file has its set-group-id bit set.
|
||||
|
||||
if test -h "$file_name" ; then
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706/14
|
||||
true "skip symlink: $file_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
if test -d "$file_name" ; then
|
||||
true "skip directory: $file_name"
|
||||
continue
|
||||
fi
|
||||
|
||||
local setuid setuid_output setsgid setsgid_output
|
||||
setuid=""
|
||||
setuid_output=""
|
||||
if test -u "$file_name" ; then
|
||||
setuid=true
|
||||
setuid_output="set-user-id"
|
||||
fi
|
||||
setsgid=""
|
||||
setsgid_output=""
|
||||
if test -g "$file_name" ; then
|
||||
setsgid=true
|
||||
setsgid_output="set-group-id"
|
||||
fi
|
||||
|
||||
local setuid_or_setsgid
|
||||
setuid_or_setsgid=""
|
||||
if [ "$setuid" = "true" ] || [ "$setsgid" = "true" ]; then
|
||||
setuid_or_setsgid=true
|
||||
fi
|
||||
if [ "$setuid_or_setsgid" = "" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
## Remove suid / gid and execute permission for 'group' and 'others'.
|
||||
## Similar to: chmod og-ugx /path/to/filename
|
||||
## Removing execution permission is useful to make binaries such as 'su' fail closed rather
|
||||
## than fail open if suid was removed from these.
|
||||
## Do not remove read access since no security benefit and easier to manually undo for users.
|
||||
## Are there suid or sgid binaries which are still useful if suid / sgid has been removed from these?
|
||||
new_mode="744"
|
||||
|
||||
local is_exact_whitelisted
|
||||
is_exact_whitelisted=""
|
||||
for white_list_entry in $exact_white_list ; do
|
||||
if [ "$file_name" = "$white_list_entry" ]; then
|
||||
is_exact_whitelisted="true"
|
||||
## Stop looping through the whitelist.
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
local is_match_whitelisted
|
||||
is_match_whitelisted=""
|
||||
for matchwhite_list_entry in $match_white_list ; do
|
||||
if echo "$file_name" | grep -q "$matchwhite_list_entry" ; then
|
||||
is_match_whitelisted="true"
|
||||
## Stop looping through the match_white_list.
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
local is_disable_whitelisted
|
||||
is_disable_whitelisted=""
|
||||
for disablematch_list_entry in $disable_white_list ; do
|
||||
if echo "$file_name" | grep -q "$disablematch_list_entry" ; then
|
||||
is_disable_whitelisted="true"
|
||||
## Stop looping through the disablewhitelist.
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$whitelists_disable_all" = "true" ]; then
|
||||
true "INFO: whitelists_disable_all=true - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'"
|
||||
elif [ "$is_disable_whitelisted" = "true" ]; then
|
||||
echo "INFO: white list disabled - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'"
|
||||
else
|
||||
if [ "$is_exact_whitelisted" = "true" ]; then
|
||||
echo "INFO: SKIP whitelisted - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode'"
|
||||
continue
|
||||
fi
|
||||
if [ "$is_match_whitelisted" = "true" ]; then
|
||||
echo "INFO: SKIP matchwhitelisted - $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode' | matchwhite_list_entry: '$matchwhite_list_entry'"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "INFO: $setuid_output $setsgid_output found - file_name: '$file_name' | existing_mode: '$existing_mode' | new_mode: '$new_mode'"
|
||||
|
||||
if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$file_name" >/dev/null ; then
|
||||
true "OK Existing mode already saved previously. No need to save again."
|
||||
else
|
||||
## Save existing_mode in separate database.
|
||||
## Not using --update as not intending to enforce existing_mode.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$file_name"
|
||||
fi
|
||||
|
||||
## No need to check "dpkg-statoverride --list" for existing entries.
|
||||
## If existing_mode was correct already, we would not have reached this point.
|
||||
## Since existing_mode is incorrect, remove from dpkg-statoverride and re-add.
|
||||
|
||||
## Remove from real database.
|
||||
echo_wrapper_silent_ignore dpkg-statoverride --remove "$file_name"
|
||||
|
||||
## Remove from separate database.
|
||||
echo_wrapper_silent_ignore dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$file_name"
|
||||
|
||||
## Add to real database and use --update to make changes on disk.
|
||||
echo_wrapper_audit dpkg-statoverride --add --update "$existing_owner" "$existing_group" "$new_mode" "$file_name"
|
||||
|
||||
## Not using --update as this is only for recording.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$existing_owner" "$existing_group" "$new_mode" "$file_name"
|
||||
|
||||
## /lib will hit ARG_MAX if using bash 'shopt -s globstar' and '/lib/**'.
|
||||
## Using 'find' with '-perm /u=s,g=s' is faster and avoids ARG_MAX.
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706/17
|
||||
done < <( find "$fso_to_process" -perm /u=s,g=s -print0 | xargs -I{} -0 stat -c "%n %a %U %G" {} )
|
||||
|
||||
## Sanity test.
|
||||
if [ ! "$should_be_counter" = "$counter_actual" ]; then
|
||||
echo "INFO: fso_to_process: '$fso_to_process' | counter_actual : '$counter_actual'"
|
||||
echo "INFO: fso_to_process: '$fso_to_process' | should_be_counter: '$should_be_counter'"
|
||||
exit_code=202
|
||||
echo "ERROR: counter does not check out." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
set_file_perms() {
|
||||
echo "INFO: START parsing config_file: '$config_file'"
|
||||
local line
|
||||
while read -r line; do
|
||||
if [ "$line" = "" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$line" =~ ^# ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$line" =~ [0-9a-zA-Z/] ]]; then
|
||||
true "OK line contains only white listed characters."
|
||||
else
|
||||
exit_code=200
|
||||
echo "ERROR: cannot parse line with invalid character. line: '$line'" >&2
|
||||
## Safer to exit with error in this case.
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706/59
|
||||
exit "$exit_code"
|
||||
fi
|
||||
|
||||
if [ "$line" = 'whitelists_disable_all=true' ]; then
|
||||
whitelists_disable_all=true
|
||||
echo "INFO: whitelists_disable_all=true - all whitelists disabled."
|
||||
continue
|
||||
fi
|
||||
|
||||
#global fso
|
||||
local mode_from_config owner_from_config group_from_config capability_from_config
|
||||
if ! read -r fso mode_from_config owner_from_config group_from_config capability_from_config <<< "$line" ; then
|
||||
exit_code=201
|
||||
echo "ERROR: cannot parse. line: '$line'" >&2
|
||||
## Debugging.
|
||||
du -hs /tmp || true
|
||||
echo "test -w /tmp: '$(test -w /tmp)'" >&2 || true
|
||||
## Safer to exit with error in this case.
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706/59
|
||||
exit "$exit_code"
|
||||
fi
|
||||
|
||||
local fso_without_trailing_slash
|
||||
fso_without_trailing_slash="${fso%/}"
|
||||
|
||||
if [ "$mode_from_config" = "disablewhitelist" ]; then
|
||||
## TODO: test/add white spaces inside file name support
|
||||
disable_white_list+="$fso "
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mode_from_config" = "exactwhitelist" ]; then
|
||||
## TODO: test/add white spaces inside file name support
|
||||
exact_white_list+="$fso "
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mode_from_config" = "matchwhitelist" ]; then
|
||||
## TODO: test/add white spaces inside file name support
|
||||
match_white_list+="$fso "
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -e "$fso" ]; then
|
||||
echo "INFO: fso: '$fso' - does not exist. This is likely normal."
|
||||
continue
|
||||
fi
|
||||
|
||||
## Use dpkg-statoverride so permissions are not reset during upgrades.
|
||||
|
||||
if [ "$mode_from_config" = "nosuid" ]; then
|
||||
## If mode_from_config is "nosuid" the config does not set owner and
|
||||
## group. Therefore do not enforce owner/group check.
|
||||
|
||||
add_nosuid_statoverride_entry
|
||||
else
|
||||
local string_length_of_mode_from_config
|
||||
string_length_of_mode_from_config="${#mode_from_config}"
|
||||
if [ "$string_length_of_mode_from_config" -gt "4" ]; then
|
||||
echo "ERROR: Mode '$mode_from_config' is invalid!" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$string_length_of_mode_from_config" -lt "3" ]; then
|
||||
echo "ERROR: Mode '$mode_from_config' is invalid!" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! getent passwd | grep -q "^${owner_from_config}:" ; then
|
||||
echo "ERROR: owner_from_config '$owner_from_config' does not exist!" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
if ! getent group | grep -q "^${group_from_config}:" ; then
|
||||
echo "ERROR: group_from_config '$group_from_config' does not exist!" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
local mode_for_grep
|
||||
mode_for_grep="$mode_from_config"
|
||||
first_character_of_mode_from_config="${mode_from_config::1}"
|
||||
if [ "$first_character_of_mode_from_config" = "0" ]; then
|
||||
## Remove leading '0'.
|
||||
mode_for_grep="${mode_from_config:1}"
|
||||
fi
|
||||
|
||||
local stat_output
|
||||
stat_output=""
|
||||
if ! stat_output="$(stat -c "%n %a %U %G" "$fso_without_trailing_slash")" ; then
|
||||
echo "ERROR: failed to run 'stat' for fso_without_trailing_slash: '$fso_without_trailing_slash'!" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
local arr file_name existing_mode existing_owner existing_group
|
||||
arr=($stat_output)
|
||||
file_name="${arr[0]}"
|
||||
existing_mode="${arr[1]}"
|
||||
existing_owner="${arr[2]}"
|
||||
existing_group="${arr[3]}"
|
||||
|
||||
if [ "$arr" = "" ]; then
|
||||
echo "ERROR: arr is empty. stat_output: '$stat_output' | line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$file_name" = "" ]; then
|
||||
echo "ERROR: file_name is empty. stat_output: '$stat_output' | line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_mode" = "" ]; then
|
||||
echo "ERROR: existing_mode is empty. stat_output: '$stat_output' | line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_owner" = "" ]; then
|
||||
echo "ERROR: existing_owner is empty. stat_output: '$stat_output' | line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
if [ "$existing_group" = "" ]; then
|
||||
echo "ERROR: $existing_group is empty. stat_output: '$stat_output' | line: '$line'" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
## Check there is an entry for the fso.
|
||||
##
|
||||
## example: dpkg-statoverride --list | grep /home
|
||||
## output:
|
||||
## root root 755 /home
|
||||
##
|
||||
## dpkg-statoverride does not show leading '0'.
|
||||
local dpkg_statoverride_list_output=""
|
||||
local dpkg_statoverride_list_exit_code=0
|
||||
dpkg_statoverride_list_output="$(dpkg-statoverride --list "$fso_without_trailing_slash")" || { dpkg_statoverride_list_exit_code=$? ; true; };
|
||||
|
||||
if [ "$dpkg_statoverride_list_exit_code" = "0" ]; then
|
||||
true "There is an fso entry. Check if owner/group/mode match."
|
||||
local grep_line
|
||||
grep_line="$owner_from_config $group_from_config $mode_for_grep $fso_without_trailing_slash"
|
||||
if echo "$dpkg_statoverride_list_output" | grep -q "$grep_line" ; then
|
||||
true "OK The owner/group/mode matches. No further action required."
|
||||
else
|
||||
true "The owner/group/mode do not match, therefore remove and re-add the entry to update it."
|
||||
## fso_without_trailing_slash instead of fso to prevent
|
||||
## "dpkg-statoverride: warning: stripping trailing /"
|
||||
|
||||
if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$fso_without_trailing_slash" >/dev/null ; then
|
||||
true "OK Existing mode already saved previously. No need to save again."
|
||||
else
|
||||
## Save existing_mode in separate database.
|
||||
## Not using --update as not intending to enforce existing_mode.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$fso_without_trailing_slash"
|
||||
fi
|
||||
|
||||
echo_wrapper_silent_ignore dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$fso_without_trailing_slash"
|
||||
|
||||
## Remove from and add to real database.
|
||||
echo_wrapper_silent_ignore dpkg-statoverride --remove "$fso_without_trailing_slash"
|
||||
echo_wrapper_audit dpkg-statoverride --add --update "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash"
|
||||
|
||||
## Save in separate database.
|
||||
## Not using --update as this is only for saving.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash"
|
||||
fi
|
||||
else
|
||||
true "There is no fso entry. Therefore add one."
|
||||
|
||||
if dpkg-statoverride $dpkg_admindir_parameter_existing_mode --list "$fso_without_trailing_slash" >/dev/null ; then
|
||||
true "OK Existing mode already saved previously. No need to save again."
|
||||
else
|
||||
## Save existing_mode in separate database.
|
||||
## Not using --update as not intending to enforce existing_mode.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_existing_mode --add "$existing_owner" "$existing_group" "$existing_mode" "$fso_without_trailing_slash"
|
||||
fi
|
||||
|
||||
## Add to real database.
|
||||
echo_wrapper_audit dpkg-statoverride --add --update "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash"
|
||||
|
||||
## Save in separate database.
|
||||
## Not using --update as this is only for saving.
|
||||
echo_wrapper_silent_audit dpkg-statoverride $dpkg_admindir_parameter_new_mode --add "$owner_from_config" "$group_from_config" "$mode_from_config" "$fso_without_trailing_slash"
|
||||
fi
|
||||
fi
|
||||
if [ "$capability_from_config" = "" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$capability_from_config" = "none" ]; then
|
||||
## https://forums.whonix.org/t/disable-suid-binaries/7706/45
|
||||
# sudo setcap -r /bin/ping 2>/dev/null
|
||||
# Failed to set capabilities on file `/bin/ping' (No data available)
|
||||
# The value of the capability argument is not permitted for a file. Or the file is not a regular (non-symlink) file
|
||||
## Therefore use echo_wrapper_ignore.
|
||||
echo_wrapper_ignore setcap -r "$fso"
|
||||
getcap_output="$(getcap "$fso")"
|
||||
if [ ! "$getcap_output" = "" ]; then
|
||||
exit_code=205
|
||||
echo "ERROR: removing capabilities for fso '$fso' failed!" >&2
|
||||
continue
|
||||
fi
|
||||
else
|
||||
if ! capsh --print | grep "Bounding set" | grep -q "$capability_from_config" ; then
|
||||
echo "ERROR: capability_from_config '$capability_from_config' does not exist!" >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
## feature request: dpkg-statoverride: support for capabilities
|
||||
## https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=502580
|
||||
echo_wrapper_audit setcap "${capability_from_config}+ep" "$fso"
|
||||
fi
|
||||
done < "$config_file"
|
||||
echo "INFO: END parsing config_file: '$config_file'"
|
||||
}
|
||||
|
||||
parse_config_folder() {
|
||||
shopt -s nullglob
|
||||
for config_file in /etc/permission-hardening.d/*.conf /usr/local/etc/permission-hardening.d/*.conf; do
|
||||
set_file_perms
|
||||
done
|
||||
}
|
||||
|
||||
sanity_tests
|
||||
parse_config_folder
|
||||
|
||||
if [ ! "$exit_code" = "0" ]; then
|
||||
echo "ERROR: Will exit with non-zero exit code: '$exit_code'" >&2
|
||||
fi
|
||||
|
||||
exit "$exit_code"
|
|
@ -1,136 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [ "$1" = "all" ]; then
|
||||
remove_file="all"
|
||||
elif [ ! "$1" = "" ]; then
|
||||
remove_file="$1"
|
||||
else
|
||||
echo "ERROR: need to give parameter 'all' or a filename.
|
||||
|
||||
examples:
|
||||
|
||||
$0 all
|
||||
|
||||
$0 /usr/bin/newgrp
|
||||
" >&2
|
||||
fi
|
||||
|
||||
exit_code=0
|
||||
|
||||
dpkg_admindir_parameter_existing_mode="--admindir /var/lib/permission-hardening/existing_mode"
|
||||
dpkg_admindir_parameter_new_mode="--admindir /var/lib/permission-hardening/new_mode"
|
||||
|
||||
undo_permission_hardening() {
|
||||
if [ ! -f /var/lib/permission-hardening/existing_mode/statoverride ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local line
|
||||
|
||||
while read -r line; do
|
||||
## example line:
|
||||
## root root 4755 /usr/lib/eject/dmcrypt-get-device
|
||||
|
||||
local owner group mode file_name
|
||||
if ! read -r owner group mode file_name <<< "$line" ; then
|
||||
exit_code=201
|
||||
echo "ERROR: cannot parse line: $line" >&2
|
||||
continue
|
||||
fi
|
||||
true "owner: '$owner' group: '$group' mode: '$mode' file_name: '$file_name'"
|
||||
|
||||
if [ "$remove_file" = "all" ]; then
|
||||
do_proceed=true
|
||||
verbose_maybe=""
|
||||
else
|
||||
if [ "$remove_file" = "$file_name" ]; then
|
||||
do_proceed=true
|
||||
verbose_maybe="--verbose"
|
||||
remove_one=true
|
||||
else
|
||||
do_proceed=false
|
||||
verbose_maybe=""
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$do_proceed" = "false" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$remove_one" = "true" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
if test -e "$file_name" ; then
|
||||
chown $verbose_maybe "${owner}:${group}" "$file_name" || exit_code=202
|
||||
## chmod need to be run after chown since chown removes suid.
|
||||
## https://unix.stackexchange.com/questions/53665/chown-removes-setuid-bit-bug-or-feature
|
||||
chmod $verbose_maybe "$mode" "$file_name" || exit_code=203
|
||||
else
|
||||
echo "INFO: file_name: '$file_name' - does not exist. This is likely normal."
|
||||
fi
|
||||
|
||||
dpkg-statoverride --remove "$file_name" &>/dev/null || true
|
||||
dpkg-statoverride $dpkg_admindir_parameter_existing_mode --remove "$file_name" &>/dev/null || true
|
||||
dpkg-statoverride $dpkg_admindir_parameter_new_mode --remove "$file_name" &>/dev/null || true
|
||||
|
||||
if [ "$remove_one" = "true" ]; then
|
||||
set +x
|
||||
break
|
||||
fi
|
||||
|
||||
done < "/var/lib/permission-hardening/existing_mode/statoverride"
|
||||
}
|
||||
|
||||
undo_permission_hardening
|
||||
|
||||
if [ ! "$remove_file" = "all" ]; then
|
||||
if [ ! "$remove_one" = "true" ]; then
|
||||
echo "INFO: none removed.
|
||||
|
||||
File '$remove_file' has not removed from SUID Disabler and Permission Hardener during this invocation of this program.
|
||||
|
||||
Note: This is expected if already done earlier.
|
||||
|
||||
Note: This program expects the full path to the file. Example:
|
||||
|
||||
$0 /usr/bin/newgrp
|
||||
|
||||
The following syntax will not work:
|
||||
|
||||
$0 program-name
|
||||
|
||||
The following example will not work:
|
||||
|
||||
$0 newgrp
|
||||
|
||||
To remove all:
|
||||
|
||||
$0 all
|
||||
|
||||
This change might not be permanent (because of the permission-hardening.service systemd unit). For full instructions, see:
|
||||
https://www.whonix.org/wiki/SUID_Disabler_and_Permission_Hardener
|
||||
|
||||
To view list of changed by SUID Disabler and Permission Hardener:
|
||||
https://www.whonix.org/wiki/SUID_Disabler_and_Permission_Hardener#View_List_of_Permissions_Changed_by_SUID_Disabler_and_Permission_Hardener
|
||||
|
||||
For re-enabling any specific SUID binary:
|
||||
https://www.whonix.org/wiki/SUID_Disabler_and_Permission_Hardener#Re-Enable_Specific_SUID_Binaries
|
||||
|
||||
For completely disabling SUID Disabler and Permission Hardener:
|
||||
https://www.whonix.org/wiki/SUID_Disabler_and_Permission_Hardener#Disable_SUID_Disabler_and_Permission_Hardener"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! "$exit_code" = "0" ]; then
|
||||
echo "ERROR: Will exit with non-zero exit code: '$exit_code'" >&2
|
||||
fi
|
||||
|
||||
exit "$exit_code"
|
|
@ -1,68 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## Doing this for all users would create many issues.
|
||||
# /usr/lib/security-misc/permission-lockdown: user: root | chmod o-rwx "/root"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: daemon | chmod o-rwx "/usr/sbin"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: bin | chmod o-rwx "/bin"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: sys | chmod o-rwx "/dev"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: sync | chmod o-rwx "/bin"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: games | chmod o-rwx "/usr/games"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: man | chmod o-rwx "/var/cache/man"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: mail | chmod o-rwx "/var/mail"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: proxy | chmod o-rwx "/bin"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: backup | chmod o-rwx "/var/backups"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: systemd-timesync | chmod o-rwx "/run/systemd"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: systemd-network | chmod o-rwx "/run/systemd/netif"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: messagebus | chmod o-rwx "/var/run/dbus"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: tinyproxy | chmod o-rwx "/run/tinyproxy"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: rtkit | chmod o-rwx "/proc"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: colord | chmod o-rwx "/var/lib/colord"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: Debian-exim | chmod o-rwx "/var/spool/exim4"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: debian-tor | chmod o-rwx "/var/lib/tor"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: stunnel4 | chmod o-rwx "/var/run/stunnel4"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: iodine | chmod o-rwx "/var/run/iodine"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: apt-cacher-ng | chmod o-rwx "/var/cache/apt-cacher-ng"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: statd | chmod o-rwx "/var/lib/nfs"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: timidity | chmod o-rwx "/etc/timidity"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: uuidd | chmod o-rwx "/run/uuidd"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: _rpc | chmod o-rwx "/run/rpcbind"
|
||||
# /usr/lib/security-misc/permission-lockdown: user: geoclue | chmod o-rwx "/var/lib/geoclue"
|
||||
|
||||
home_folder_access_rights_lockdown() {
|
||||
shopt -s nullglob
|
||||
|
||||
## Not using dotglob.
|
||||
## touch /var/cache/security-misc/state-files//home/.Trash
|
||||
## touch: cannot touch '/var/cache/security-misc/state-files//home/.Trash': No such file or directory
|
||||
|
||||
local folder_name base_name
|
||||
|
||||
for folder_name in /home/* ; do
|
||||
base_name="$(basename "$folder_name")"
|
||||
if [ -f "/var/cache/security-misc/state-files/$base_name" ]; then
|
||||
continue
|
||||
fi
|
||||
if [ ! -d "$folder_name" ]; then
|
||||
continue
|
||||
fi
|
||||
if [ "$folder_name" = "/home/" ]; then
|
||||
continue
|
||||
fi
|
||||
mkdir -p /var/cache/security-misc/state-files
|
||||
echo "$0: chmod o-rwx \"$folder_name\""
|
||||
chmod o-rwx "$folder_name"
|
||||
## Create a state-file so we do this only once.
|
||||
## Therefore a user who will manually undo this, will not get
|
||||
## annoyed by this being done over and over again.
|
||||
touch "/var/cache/security-misc/state-files/$base_name"
|
||||
done
|
||||
|
||||
shopt -u nullglob
|
||||
}
|
||||
|
||||
home_folder_access_rights_lockdown
|
||||
|
||||
exit 0
|
|
@ -1,130 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## noexec in /tmp and/or /home can break some malware but also legitimate
|
||||
## applications.
|
||||
|
||||
## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
if [ -f /usr/libexec/helper-scripts/pre.bsh ]; then
|
||||
## pre.bsh would `source` the following folders:
|
||||
## /etc/remount-secure_pre.d/*.conf
|
||||
## /usr/local/etc/remount-secure_pre.d/*.conf
|
||||
source /usr/libexec/helper-scripts/pre.bsh
|
||||
fi
|
||||
|
||||
if [ -e /etc/remount-disable ] || [ -e /usr/local/etc/remount-disable ]; then
|
||||
echo "INFO: file /etc/remount-disable exists. Doing nothing."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -e /etc/exec ] || [ -e /usr/local/etc/exec ]; then
|
||||
noexec=false
|
||||
echo "INFO: Will remount with exec because file /etc/exec or /usr/local/etc/exec exists."
|
||||
else
|
||||
if [ -e /etc/noexec ] || [ -e /usr/local/etc/noexec ]; then
|
||||
noexec=true
|
||||
echo "INFO: Will remount with noexec because file /etc/noexec or /usr/local/etc/noexec exists."
|
||||
else
|
||||
echo "INFO: Will not remount with noexec because file /etc/noexec or /usr/local/etc/noexec does not exist."
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir --parents "/var/run/remount-secure"
|
||||
|
||||
if [ "$noexec" = "true" ]; then
|
||||
noexec_maybe=",noexec"
|
||||
fi
|
||||
|
||||
exit_code=0
|
||||
|
||||
mount_output="$(mount)"
|
||||
|
||||
remount_secure() {
|
||||
## ${FUNCNAME[1]} is the name of the calling function. I.e. the function
|
||||
## which called this function.
|
||||
status_file_name="${FUNCNAME[1]}"
|
||||
## example status_file_name:
|
||||
## _home
|
||||
status_file_full_path="/var/run/remount-secure/${status_file_name}"
|
||||
## example status_file_full_path:
|
||||
## /var/run/remount-secure/_home
|
||||
|
||||
## str_replace is provided by package helper-scripts.
|
||||
mount_folder="$(echo "${status_file_name}" | str_replace "_" "/")"
|
||||
## example mount_folder:
|
||||
## /home
|
||||
|
||||
mount_line_of_mount_folder="$(echo "$mount_output" | grep "$mount_folder ")" || true
|
||||
|
||||
if echo "$mount_line_of_mount_folder" | grep -q "$new_mount_options" ; then
|
||||
echo "INFO: $mount_folder has already intended mount options."
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -e "$status_file_full_path" ]; then
|
||||
echo "INFO: $mount_folder already remounted earlier. Not remounting again."
|
||||
return 0
|
||||
fi
|
||||
|
||||
## BUG: echo: write error: Broken pipe
|
||||
if echo "$mount_output" | grep -q "$mount_folder " ; then
|
||||
## Already mounted. Using remount.
|
||||
echo mount -o "remount,${new_mount_options}" "$mount_folder"
|
||||
mount -o "remount,${new_mount_options}" "$mount_folder" || exit_code=100
|
||||
else
|
||||
## Not yet mounted. Using mount bind.
|
||||
echo mount -o "$new_mount_options" --bind "$mount_folder" "$mount_folder"
|
||||
mount -o "$new_mount_options" --bind "$mount_folder" "$mount_folder" || exit_code=101
|
||||
fi
|
||||
|
||||
touch "$status_file_full_path"
|
||||
}
|
||||
|
||||
_home() {
|
||||
new_mount_options="nosuid,nodev${noexec_maybe}"
|
||||
remount_secure "$@"
|
||||
}
|
||||
|
||||
_run() {
|
||||
## https://lists.freedesktop.org/archives/systemd-devel/2015-February/028456.html
|
||||
new_mount_options="nosuid,nodev${noexec_maybe}"
|
||||
remount_secure "$@"
|
||||
}
|
||||
|
||||
_dev_shm() {
|
||||
new_mount_options="nosuid,nodev${noexec_maybe}"
|
||||
remount_secure "$@"
|
||||
}
|
||||
|
||||
_tmp() {
|
||||
new_mount_options="nosuid,nodev${noexec_maybe}"
|
||||
remount_secure "$@"
|
||||
}
|
||||
|
||||
## https://forums.whonix.org/t/re-mount-home-and-other-with-noexec-and-nosuid-among-other-useful-mount-options-for-better-security/7707/25
|
||||
# _lib() {
|
||||
# ## Not using noexec on /lib.
|
||||
# new_mount_options="nosuid,nodev"
|
||||
# remount_secure "$@"
|
||||
# }
|
||||
|
||||
end() {
|
||||
exit $exit_code
|
||||
}
|
||||
|
||||
main() {
|
||||
_home "$@"
|
||||
_run "$@"
|
||||
_dev_shm "$@"
|
||||
_tmp "$@"
|
||||
#_lib "$@"
|
||||
end "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
|
@ -1,37 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2012 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
if [ -f /usr/libexec/helper-scripts/pre.bsh ]; then
|
||||
## pre.bsh would `source` the following folders:
|
||||
## /etc/remove-system.map_pre.d/*.conf
|
||||
## /usr/local/etc/remove-system.map_pre.d/*.conf
|
||||
source /usr/libexec/helper-scripts/pre.bsh
|
||||
fi
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
system_map_location="/boot/System.map* /usr/src/*/System.map* /lib/modules/*/*/System.map* /System.map*"
|
||||
|
||||
counter=0
|
||||
for filename in ${system_map_location} ; do
|
||||
counter=$(( counter + 1 ))
|
||||
done
|
||||
|
||||
if [ "$counter" -ge "1" ]; then
|
||||
echo "Deleting system.map files..."
|
||||
fi
|
||||
|
||||
## Removes the System.map files as they are only used for debugging or malware.
|
||||
for filename in ${system_map_location} ; do
|
||||
if [ -f "${filename}" ]; then
|
||||
## 'shred' with '--verbose' is too chatty. (7 lines)
|
||||
shred --force --zero -u "${filename}"
|
||||
echo "removed '${filename}'"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$counter" -ge "1" ]; then
|
||||
echo "Done. Success."
|
||||
fi
|
|
@ -1,354 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
## Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
|
||||
## See the file COPYING for copying conditions.
|
||||
|
||||
## VirusForget is inspired by Christopher Laprise.
|
||||
## tasket@protonmail.com
|
||||
## https://github.com/tasket
|
||||
## https://www.patreon.com/tasket/creators
|
||||
## Because of his work on Qubes-VM-Hardening.
|
||||
## https://github.com/tasket/Qubes-VM-hardening
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
|
||||
error_handler() {
|
||||
## TODO
|
||||
exit 1
|
||||
}
|
||||
|
||||
trap error_handler ERR
|
||||
|
||||
root_check() {
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "ERROR: must be run as root! sudo $0"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
parse_cmd_options() {
|
||||
## Thanks to:
|
||||
## http://mywiki.wooledge.org/BashFAQ/035
|
||||
|
||||
while :
|
||||
do
|
||||
case $1 in
|
||||
--user)
|
||||
user_name="$2"
|
||||
if [ "$user_name" = "" ]; then
|
||||
echo "ERROR: --user needs username as argument!" >&2
|
||||
shift
|
||||
exit 1
|
||||
else
|
||||
shift 2
|
||||
fi
|
||||
;;
|
||||
--simulate)
|
||||
test_mode="true"
|
||||
shift
|
||||
;;
|
||||
--unittest)
|
||||
unit_test="true"
|
||||
shift
|
||||
;;
|
||||
--commit)
|
||||
commit="true"
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
clean="true"
|
||||
shift
|
||||
;;
|
||||
--check)
|
||||
check="true"
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
echo "ERROR: unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
## If there are input files (for example) that follow the options, they
|
||||
## will remain in the "$@" positional parameters.
|
||||
|
||||
if [ "$user_name" = "" ]; then
|
||||
echo "ERROR: must set --user username" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
variables() {
|
||||
chfiles+=" .bashrc "
|
||||
chfiles+=" .bash_profile "
|
||||
chfiles+=" .bash_login "
|
||||
chfiles+=" .bash_logout "
|
||||
chfiles+=" .profile "
|
||||
chfiles+=" .pam_environment "
|
||||
chfiles+=" .xprofile "
|
||||
chfiles+=" .xinitrc "
|
||||
chfiles+=" .xserverrc "
|
||||
chfiles+=" .Xsession "
|
||||
chfiles+=" .xsession "
|
||||
chfiles+=" .xsessionrc "
|
||||
chfiles+=" .virusforgetunitestone "
|
||||
chfiles+=" .virusforgetunitesttwo "
|
||||
|
||||
chdirs+=" bin "
|
||||
chdirs+=" .local/bin "
|
||||
chdirs+=" .config/autostart "
|
||||
chdirs+=" .config/plasma-workspace/env "
|
||||
chdirs+=" .config/plasma-workspace/shutdown "
|
||||
chdirs+=" .config/autostart-scripts "
|
||||
chdirs+=" .config/systemd "
|
||||
|
||||
## TODO
|
||||
privdirs+=" /rw/config "
|
||||
privdirs+=" /rw/usrlocal "
|
||||
privdirs+=" /rw/bind-dirs "
|
||||
|
||||
backup_folder="/home/virusforget/backup"
|
||||
dangerous_folder="/home/virusforget/dangerous"
|
||||
}
|
||||
|
||||
init() {
|
||||
adduser --home /home/virusforget --quiet --system --group virusforget
|
||||
home_folder="/home/$user_name"
|
||||
}
|
||||
|
||||
process_file_system_objects() {
|
||||
if [ "$store" = "true" ]; then
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo Simulate: rm -r -f "$backup_folder"
|
||||
else
|
||||
rm -r -f "$backup_folder"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
true
|
||||
else
|
||||
mkdir -p "$backup_folder"
|
||||
fi
|
||||
|
||||
process_files
|
||||
process_folders
|
||||
}
|
||||
|
||||
process_files() {
|
||||
for file_name in $chfiles ; do
|
||||
full_path_original="$home_folder/$file_name"
|
||||
full_path_original_dirname="${full_path_original%/*}"
|
||||
full_path_backup="$backup_folder/$file_name"
|
||||
full_path_dangerous="$dangerous_folder/$file_name"
|
||||
full_path_dangerous_dirname="${full_path_dangerous%/*}"
|
||||
if [ "$store" = "true" ]; then
|
||||
if [ -e "$full_path_original" ]; then
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo Simulate: cp --no-dereference --archive "$full_path_original" "$backup_folder/"
|
||||
else
|
||||
cp --no-dereference --archive "$full_path_original" "$backup_folder/"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
check_file_walker
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
process_folders() {
|
||||
for folder_name in $chdirs ; do
|
||||
full_folder_name="$home_folder/$folder_name"
|
||||
|
||||
if [ -e "$full_folder_name" ]; then
|
||||
find "$full_folder_name" -print0 | \
|
||||
while IFS= read -r -d '' line; do
|
||||
true "line: $line"
|
||||
if [ "$full_folder_name" = "$line" ]; then
|
||||
continue
|
||||
fi
|
||||
full_path_original="$line"
|
||||
full_path_original_dirname="${full_path_original%/*}"
|
||||
## remove prepeneded $home_folder from $full_path_original
|
||||
temp_one="$home_folder/"
|
||||
temp="${full_path_original/#$temp_one/""}"
|
||||
full_path_backup="$backup_folder/$temp"
|
||||
full_path_backup_dirname="${full_path_backup%/*}"
|
||||
full_path_dangerous="$dangerous_folder/$temp"
|
||||
full_path_dangerous_dirname="${full_path_dangerous%/*}"
|
||||
|
||||
if [ "$store" = "true" ]; then
|
||||
if [ -d "$full_path_original" ]; then
|
||||
true "ok"
|
||||
else
|
||||
## Not needed since starting with new backup folder anyhow.
|
||||
#if [ -e "$full_path_backup" ]; then
|
||||
# echo chattr -i "$full_path_backup"
|
||||
# echo rm "$full_path_backup"
|
||||
#fi
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo Simulate: cp --no-dereference --archive "$full_path_original" "$full_path_backup_dirname/"
|
||||
else
|
||||
mkdir -p "$full_path_backup_dirname"
|
||||
cp --no-dereference --archive "$full_path_original" "$full_path_backup_dirname/"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
check_file_walker
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_file_walker() {
|
||||
if [ -e "$full_path_backup" ]; then
|
||||
if [ -e "$full_path_original" ]; then
|
||||
if [ -d "$full_path_original" ]; then
|
||||
## REVIEW: ok to skip directory?
|
||||
true
|
||||
return 0
|
||||
fi
|
||||
if diff "$full_path_original" "$full_path_backup" &>/dev/null ; then
|
||||
true "OK"
|
||||
else
|
||||
echo "Difference detected! changed file: $full_path_original backup: $full_path_backup" >&2
|
||||
unexpected_file "$full_path_original"
|
||||
fi
|
||||
else
|
||||
echo "Missing file detected! missing: $full_path_original" >&2
|
||||
restore_file
|
||||
fi
|
||||
else
|
||||
if [ -e "$full_path_original" ]; then
|
||||
if [ -d "$full_path_original" ]; then
|
||||
## REVIEW: ignore ok?
|
||||
true
|
||||
return 0
|
||||
fi
|
||||
echo "Extraneous file! $full_path_original" >&2
|
||||
unexpected_file "$full_path_original"
|
||||
else
|
||||
true "OK"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
unexpected_file() {
|
||||
if [ -d "$full_path_original" ]; then
|
||||
## REVIEW: ignore ok?
|
||||
true
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$full_path_dangerous_dirname"
|
||||
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo "Simulate backup of current version... $full_path_original" >&2
|
||||
echo cp "$full_path_original" --no-dereference --archive --backup=existing "$full_path_dangerous"
|
||||
elif [ "$clean" = "true" ]; then
|
||||
echo "Creating backup of current version... $full_path_original" >&2
|
||||
echo cp "$full_path_original" --no-dereference --archive --backup=existing "$full_path_dangerous"
|
||||
cp "$full_path_original" --no-dereference --archive --backup=existing "$full_path_dangerous"
|
||||
echo "Created backup." >&2
|
||||
fi
|
||||
|
||||
if test -h "$full_path_original" ; then
|
||||
echo "is a symlink: $full_path_original" >&2
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo "Simulate only. unexpected symlink. Removing... unlink '$full_path_original'" >&2
|
||||
echo unlink "$full_path_original"
|
||||
elif [ "$clean" = "true" ]; then
|
||||
echo "unexpected symlink. Removing... unlink '$full_path_original'" >&2
|
||||
unlink "$full_path_original"
|
||||
echo "Removed unexpect symlink." >&2
|
||||
fi
|
||||
else
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo "Simulate deleting modified version '$full_path_original'." >&2
|
||||
echo rm "$full_path_original" >&2
|
||||
elif [ "$clean" = "true" ]; then
|
||||
## chattr fails on symlinks such as symlink to /dev/random.
|
||||
chattr -i "$full_path_original"
|
||||
echo "Deleting modified version '$full_path_original'." >&2
|
||||
rm "$full_path_original" >&2
|
||||
echo "Deleted '$full_path_original'." >&2
|
||||
fi
|
||||
|
||||
echo "View the diff:" >&2
|
||||
echo "diff $full_path_original $full_path_dangerous" >&2
|
||||
fi
|
||||
|
||||
echo "" >&2
|
||||
|
||||
restore_file
|
||||
}
|
||||
|
||||
restore_file() {
|
||||
if [ "$test_mode" = "true" ]; then
|
||||
echo "Simulate restoring file... $full_path_original" >&2
|
||||
echo cp --no-dereference --archive "$full_path_backup" "$full_path_original"
|
||||
echo "" >&2
|
||||
elif [ "$clean" = "true" ]; then
|
||||
echo "Restoring file... $full_path_original" >&2
|
||||
echo mkdir --parents "$full_path_original_dirname" >&2
|
||||
mkdir --parents "$full_path_original_dirname"
|
||||
if [ ! "$home_folder" = "$full_path_original_dirname" ]; then
|
||||
chown --recursive "$user_name:$user_name" "$full_path_original_dirname"
|
||||
fi
|
||||
echo cp --no-dereference --archive "$full_path_backup" "$full_path_original"
|
||||
cp --no-dereference --archive "$full_path_backup" "$full_path_original" >&2
|
||||
echo "Restored." >&2
|
||||
echo "" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
unit_test_one() {
|
||||
if [ ! "$unit_test" = "true" ]; then
|
||||
return 0
|
||||
fi
|
||||
echo "x" >> /home/user/.virusforgetunitestone
|
||||
test -f /home/user/.virusforgetunitestone
|
||||
}
|
||||
|
||||
unit_test_two() {
|
||||
if [ ! "$unit_test" = "true" ]; then
|
||||
return 0
|
||||
fi
|
||||
rm /home/user/.virusforgetunitestone
|
||||
echo "x" >> /home/user/.virusforgetunitesttwo
|
||||
test -f /home/user/.virusforgetunitesttwo
|
||||
echo "x" >> /home/user/.config/systemd/user/virusforgetunittest
|
||||
test -f /home/user/.config/systemd/user/virusforgetunittest
|
||||
if test -h /home/user/.config/systemd/user/virusforgetunittestsymlink ; then
|
||||
unlink /home/user/.config/systemd/user/virusforgetunittestsymlink
|
||||
fi
|
||||
ln -s /dev/random /home/user/.config/systemd/user/virusforgetunittestsymlink
|
||||
}
|
||||
|
||||
root_check
|
||||
parse_cmd_options "$@"
|
||||
init
|
||||
variables
|
||||
unit_test_one
|
||||
|
||||
if [ "$commit" = "true" ]; then
|
||||
store=true
|
||||
process_file_system_objects
|
||||
fi
|
||||
|
||||
unit_test_two
|
||||
|
||||
if [ "$check" = "true" ]; then
|
||||
store=false
|
||||
process_file_system_objects
|
||||
fi
|
Loading…
Add table
Add a link
Reference in a new issue